From patchwork Mon Sep 28 13:45:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Beno=C3=AEt_Th=C3=A9baudeau?= X-Patchwork-Id: 523345 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id A72E21401AF for ; Mon, 28 Sep 2015 23:54:12 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B5BB64B942; Mon, 28 Sep 2015 15:54:00 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6peolVRvY02d; Mon, 28 Sep 2015 15:54:00 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1CA4C4B943; Mon, 28 Sep 2015 15:53:42 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 440B94B923 for ; Mon, 28 Sep 2015 15:51:12 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id nJj97CblcUGD for ; Mon, 28 Sep 2015 15:51:12 +0200 (CEST) X-Greylist: delayed 300 seconds by postgrey-1.34 at theia; Mon, 28 Sep 2015 15:51:08 CEST X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from authsmtp.register.it (authsmtp72.register.it [195.110.101.56]) by theia.denx.de (Postfix) with ESMTP id 066824B8E5 for ; Mon, 28 Sep 2015 15:51:08 +0200 (CEST) Received: from rad-ubuntu.home ([90.25.112.137]) by paganini34 with id Ndm31r01b2xv6ya01dm73F; Mon, 28 Sep 2015 15:46:07 +0200 X-Rid: benoit@wsystem.com@90.25.112.137 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= To: u-boot@lists.denx.de Date: Mon, 28 Sep 2015 15:45:28 +0200 Message-Id: <1443447932-14139-1-git-send-email-benoit@wsystem.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <807994631.1713509.1365795559751.JavaMail.root@advansee.com> References: <807994631.1713509.1365795559751.JavaMail.root@advansee.com> MIME-Version: 1.0 X-Mailman-Approved-At: Mon, 28 Sep 2015 15:53:32 +0200 Cc: Tom Rini , =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Subject: [U-Boot] [PATCH 1/5] fs/fat/fat_write: Fix buffer alignments X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 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" set_cluster() was using a temporary buffer without enforcing its alignment for DMA and cache. Moreover, it did not check the alignment of the passed buffer, which can come directly from applicative code or from the user. This could cause random data corruption, which has been observed on i.MX25 writing to an SD card. Fix this by only passing ARCH_DMA_MINALIGN-aligned buffers to disk_write(), which requires the introduction of a buffer bouncing mechanism for the misaligned buffers passed to set_cluster(). By the way, improve the handling of the corresponding return values from disk_write(): - print them with debug() in case of error, - consider that there is an error is disk_write() returns a smaller block count than the requested one, not only if its return value is negative. After this change, set_cluster() and get_cluster() are almost symmetrical. Signed-off-by: Benoît Thébaudeau --- fs/fat/fat_write.c | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index adb6940..d0d9df7 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -555,8 +555,9 @@ static int set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) { - int idx = 0; + __u32 idx = 0; __u32 startsect; + int ret; if (clustnum > 0) startsect = mydata->data_begin + @@ -566,26 +567,45 @@ set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, debug("clustnum: %d, startsect: %d\n", clustnum, startsect); - if ((size / mydata->sect_size) > 0) { - if (disk_write(startsect, size / mydata->sect_size, buffer) < 0) { - debug("Error writing data\n"); + if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) { + ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); + + printf("FAT: Misaligned buffer address (%p)\n", buffer); + + while (size >= mydata->sect_size) { + memcpy(tmpbuf, buffer, mydata->sect_size); + ret = disk_write(startsect++, 1, tmpbuf); + if (ret != 1) { + debug("Error writing data (got %d)\n", ret); + return -1; + } + + buffer += mydata->sect_size; + size -= mydata->sect_size; + } + } else if (size >= mydata->sect_size) { + idx = size / mydata->sect_size; + ret = disk_write(startsect, idx, buffer); + if (ret != idx) { + debug("Error writing data (got %d)\n", ret); return -1; } + + startsect += idx; + idx *= mydata->sect_size; + buffer += idx; + size -= idx; } - if (size % mydata->sect_size) { - __u8 tmpbuf[mydata->sect_size]; + if (size) { + ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); - idx = size / mydata->sect_size; - buffer += idx * mydata->sect_size; - memcpy(tmpbuf, buffer, size % mydata->sect_size); - - if (disk_write(startsect + idx, 1, tmpbuf) < 0) { - debug("Error writing data\n"); + memcpy(tmpbuf, buffer, size); + ret = disk_write(startsect, 1, tmpbuf); + if (ret != 1) { + debug("Error writing data (got %d)\n", ret); return -1; } - - return 0; } return 0;