From patchwork Tue Mar 29 19:35:46 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Remy Bohmer X-Patchwork-Id: 88840 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 043A0B6EFE for ; Wed, 30 Mar 2011 06:36:07 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1F5A32809E; Tue, 29 Mar 2011 21:36:05 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 rNSVB1I4y6El; Tue, 29 Mar 2011 21:36:04 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 552C828091; Tue, 29 Mar 2011 21:36:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 209D728091 for ; Tue, 29 Mar 2011 21:36:02 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 UX+7CU2mepNc for ; Tue, 29 Mar 2011 21:36:01 +0200 (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 mail-ey0-f172.google.com (mail-ey0-f172.google.com [209.85.215.172]) by theia.denx.de (Postfix) with ESMTPS id 0854D28089 for ; Tue, 29 Mar 2011 21:35:59 +0200 (CEST) Received: by eye13 with SMTP id 13so173933eye.3 for ; Tue, 29 Mar 2011 12:35:59 -0700 (PDT) Received: by 10.213.97.70 with SMTP id k6mr427796ebn.75.1301427359175; Tue, 29 Mar 2011 12:35:59 -0700 (PDT) Received: from localhost (541EDD7F.cm-5-7d.dynamic.ziggo.nl [84.30.221.127]) by mx.google.com with ESMTPS id w59sm3724018eeh.24.2011.03.29.12.35.56 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 29 Mar 2011 12:35:57 -0700 (PDT) From: Remy Bohmer To: u-boot@lists.denx.de, Wolfgang Denk Date: Tue, 29 Mar 2011 21:35:46 +0200 Message-Id: <1301427346-7581-1-git-send-email-linux@bohmer.net> X-Mailer: git-send-email 1.7.4.2 Cc: Erik Hansen Subject: [U-Boot] [PATCH-v2] fat32 root directory handling X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Erik Hansen Fat directory handling didn't check reaching the end of the root directory. It relied on a stop condition based on a directory entry with a name starting with a '\0' character. This check in itself is wrong ('\0' indicates free entry, not end_of_directory) but outside the scope of this fix. For FAT32, the end of the rootdir is reached when the end of the cluster chain is reached. The code didn't check this condition and started to read an incorrect cluster. This caused a subsequent read request of a sector outside the range of the usb stick in use. On its turn, the usb stick protested with a stall handshake. Both FAT32 and non-FAT32 (FAT16/FAT12) end or rootdir checks have been put in. Signed-off-by: Erik Hansen Signed-off-by: Remy Bohmer --- V2: Removed added new line I pick this patch up from here since this patch fixes a long standing issue we have with several USB sticks. fs/fat/fat.c | 37 +++++++++++++++++++++++-------------- 1 files changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index a75e4f2..c450bf6 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -209,7 +209,7 @@ static __u32 get_fatent (fsdata *mydata, __u32 entry) /* Read a new block of FAT entries into the cache. */ if (bufnum != mydata->fatbufnum) { - int getsize = FATBUFSIZE / FS_BLOCK_SIZE; + __u32 getsize = FATBUFSIZE / FS_BLOCK_SIZE; __u8 *bufptr = mydata->fatbuf; __u32 fatlength = mydata->fatlength; __u32 startblock = bufnum * FATBUFBLOCKS; @@ -279,7 +279,7 @@ static int get_cluster (fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) { - int idx = 0; + __u32 idx = 0; __u32 startsect; if (clustnum > 0) { @@ -767,12 +767,13 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize, dir_entry *dentptr; __u16 prevcksum = 0xffff; char *subname = ""; - int cursect; + __u32 cursect; int idx, isdir = 0; int files = 0, dirs = 0; long ret = 0; int firsttime; - int root_cluster; + __u32 root_cluster; + int rootdir_size = 0; int j; if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) { @@ -798,8 +799,6 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize, mydata->data_begin = mydata->rootdir_sect - (mydata->clust_size * 2); } else { - int rootdir_size; - rootdir_size = ((bs.dir_entries[1] * (int)256 + bs.dir_entries[0]) * sizeof(dir_entry)) / @@ -1006,20 +1005,18 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize, * root directory clusters when a cluster has been * completely processed. */ - if ((mydata->fatsize == 32) && (++j == mydata->clust_size)) { - int nxtsect; - int nxt_clust; + ++j; + int fat32_end = 0; + if ((mydata->fatsize == 32) && (j == mydata->clust_size)) { + int nxtsect = 0; + int nxt_clust = 0; nxt_clust = get_fatent(mydata, root_cluster); + fat32_end = CHECK_CLUST(nxt_clust, 32); nxtsect = mydata->data_begin + (nxt_clust * mydata->clust_size); - debug("END LOOP: sect=%d, root_clust=%d, " - "n_sect=%d, n_clust=%d\n", - cursect, root_cluster, - nxtsect, nxt_clust); - root_cluster = nxt_clust; cursect = nxtsect; @@ -1027,6 +1024,18 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize, } else { cursect++; } + + /* If end of rootdir reached */ + if ((mydata->fatsize == 32 && fat32_end) || + (mydata->fatsize != 32 && j == rootdir_size)) { + if (dols == LS_ROOT) { + printf("\n%d file(s), %d dir(s)\n\n", + files, dirs); + return 0; + } else { + return -1; + } + } } rootdir_done: