diff mbox series

[U-Boot,v3,3/9] fat/fs: convert to directory iterators

Message ID 20170909171606.20029-4-robdclark@gmail.com
State Accepted
Delegated to: Tom Rini
Headers show
Series fs/fat: cleanups + readdir implementation | expand

Commit Message

Rob Clark Sept. 9, 2017, 5:15 p.m. UTC
And drop a whole lot of ugly code!

Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Łukasz Majewski <lukma@denx.de>
---
 fs/fat/fat.c  | 722 +++++++---------------------------------------------------
 include/fat.h |   6 -
 2 files changed, 76 insertions(+), 652 deletions(-)

Comments

Simon Glass Sept. 12, 2017, 12:29 p.m. UTC | #1
On 9 September 2017 at 11:15, Rob Clark <robdclark@gmail.com> wrote:
> And drop a whole lot of ugly code!
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> Reviewed-by: Łukasz Majewski <lukma@denx.de>
> ---
>  fs/fat/fat.c  | 722 +++++++---------------------------------------------------
>  include/fat.h |   6 -
>  2 files changed, 76 insertions(+), 652 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>
Tom Rini Sept. 16, 2017, 2:32 a.m. UTC | #2
On Sat, Sep 09, 2017 at 01:15:54PM -0400, Rob Clark wrote:

> And drop a whole lot of ugly code!
> 
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> Reviewed-by: Łukasz Majewski <lukma@denx.de>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!
Adam Ford Sept. 16, 2017, 8:32 p.m. UTC | #3
On Fri, Sep 15, 2017 at 9:32 PM, Tom Rini <trini@konsulko.com> wrote:
>
> On Sat, Sep 09, 2017 at 01:15:54PM -0400, Rob Clark wrote:
>
> > And drop a whole lot of ugly code!
> >
> > Signed-off-by: Rob Clark <robdclark@gmail.com>
> > Reviewed-by: Łukasz Majewski <lukma@denx.de>
> > Reviewed-by: Simon Glass <sjg@chromium.org>
>
> Applied to u-boot/master, thanks!
>

According to git bisect, this patch seems to break the booting of am3517_evm

It just displays:

U-Boot SPL 2017.09-00135-g8eafae2 (Sep 16 2017 - 15:23:16)
Trying to boot from MMC1

Then hangs.

It does, however the same patch boots just fine on
omap3_logic_defconfig which is an OMAP3630/DM3730 board.

da850evm_defconfig (OMAP-L138) is also booting just fine.

I'm going to investigate it further to see why just 1/3 boards seems impacted.

adam

>
> --
> Tom
>
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> https://lists.denx.de/listinfo/u-boot
>
Rob Clark Sept. 16, 2017, 8:42 p.m. UTC | #4
On Sat, Sep 16, 2017 at 4:32 PM, Adam Ford <aford173@gmail.com> wrote:
> On Fri, Sep 15, 2017 at 9:32 PM, Tom Rini <trini@konsulko.com> wrote:
>>
>> On Sat, Sep 09, 2017 at 01:15:54PM -0400, Rob Clark wrote:
>>
>> > And drop a whole lot of ugly code!
>> >
>> > Signed-off-by: Rob Clark <robdclark@gmail.com>
>> > Reviewed-by: Łukasz Majewski <lukma@denx.de>
>> > Reviewed-by: Simon Glass <sjg@chromium.org>
>>
>> Applied to u-boot/master, thanks!
>>
>
> According to git bisect, this patch seems to break the booting of am3517_evm
>
> It just displays:
>
> U-Boot SPL 2017.09-00135-g8eafae2 (Sep 16 2017 - 15:23:16)
> Trying to boot from MMC1
>
> Then hangs.
>
> It does, however the same patch boots just fine on
> omap3_logic_defconfig which is an OMAP3630/DM3730 board.
>
> da850evm_defconfig (OMAP-L138) is also booting just fine.
>
> I'm going to investigate it further to see why just 1/3 boards seems impacted.
>

Tom reported a similar fail.. although I am failing to reproduce it in
sandbox w/ a copy of his partition, so maybe it is somehow hw
specific?  If you could, debug logs w/
https://hastebin.com/raw/fijazebiso applied in before/after case would
be useful.. maybe I could spot something from that?

BR,
-R
Adam Ford Sept. 17, 2017, 11:08 a.m. UTC | #5
On Sat, Sep 16, 2017 at 3:42 PM, Rob Clark <robdclark@gmail.com> wrote:
> On Sat, Sep 16, 2017 at 4:32 PM, Adam Ford <aford173@gmail.com> wrote:
>> On Fri, Sep 15, 2017 at 9:32 PM, Tom Rini <trini@konsulko.com> wrote:
>>>
>>> On Sat, Sep 09, 2017 at 01:15:54PM -0400, Rob Clark wrote:
>>>
>>> > And drop a whole lot of ugly code!
>>> >
>>> > Signed-off-by: Rob Clark <robdclark@gmail.com>
>>> > Reviewed-by: Łukasz Majewski <lukma@denx.de>
>>> > Reviewed-by: Simon Glass <sjg@chromium.org>
>>>
>>> Applied to u-boot/master, thanks!
>>>
>>
>> According to git bisect, this patch seems to break the booting of am3517_evm
>>
>> It just displays:
>>
>> U-Boot SPL 2017.09-00135-g8eafae2 (Sep 16 2017 - 15:23:16)
>> Trying to boot from MMC1
>>
>> Then hangs.
>>
>> It does, however the same patch boots just fine on
>> omap3_logic_defconfig which is an OMAP3630/DM3730 board.
>>
>> da850evm_defconfig (OMAP-L138) is also booting just fine.
>>
>> I'm going to investigate it further to see why just 1/3 boards seems impacted.
>>
>
> Tom reported a similar fail.. although I am failing to reproduce it in
> sandbox w/ a copy of his partition, so maybe it is somehow hw
> specific?  If you could, debug logs w/
> https://hastebin.com/raw/fijazebiso applied in before/after case would
> be useful.. maybe I could spot something from that?
>

Adding the debug to master made no difference.  No debug messages appeared.
Interestingly enough, some junk appeard, and the name of U-Boot name
wasn't correctly displayed:

**Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
Trying to boot from MMC1

(hang)

Could there a be some memory overflow somewhere?

Adding the debug to the last working commit, yielded the following:

U-Boot SPL 2017.09-00134-ge71f88d-dirty (Sep 17 2017 - 06:03:28)
Trying to boot from MMC1
reading u-boot.img
VFAT Support enabled
FAT16, fat_sect: 1, fatlength: 200
Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
Data begins at: 417
Sector size: 512, cluster size: 8
FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=d
RootMismatch: |mlo||
Rootvfatname: |u-boot.img|
RootName: u-boot.img, start: 0x98, size:  0x83708
Filesize: u bytes
u bytes
gc - clustnum: 152, startsect: 1633
Size: 538376, got: u
reading u-boot.img
VFAT Support enabled
FAT16, fat_sect: 1, fatlength: 200
Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
Data begins at: 417
Sector size: 512, cluster size: 8
FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=d
RootMismatch: |mlo||
Rootvfatname: |u-boot.img|
RootName: u-boot.img, start: 0x98, size:  0x83708
Filesize: u bytes
u bytes

I truncated it, because after that, it seems to just be showing
entries and offsets over and over again.

adam
> BR,
> -R
Rob Clark Sept. 17, 2017, 12:28 p.m. UTC | #6
On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
> On Sat, Sep 16, 2017 at 3:42 PM, Rob Clark <robdclark@gmail.com> wrote:
>> On Sat, Sep 16, 2017 at 4:32 PM, Adam Ford <aford173@gmail.com> wrote:
>>> On Fri, Sep 15, 2017 at 9:32 PM, Tom Rini <trini@konsulko.com> wrote:
>>>>
>>>> On Sat, Sep 09, 2017 at 01:15:54PM -0400, Rob Clark wrote:
>>>>
>>>> > And drop a whole lot of ugly code!
>>>> >
>>>> > Signed-off-by: Rob Clark <robdclark@gmail.com>
>>>> > Reviewed-by: Łukasz Majewski <lukma@denx.de>
>>>> > Reviewed-by: Simon Glass <sjg@chromium.org>
>>>>
>>>> Applied to u-boot/master, thanks!
>>>>
>>>
>>> According to git bisect, this patch seems to break the booting of am3517_evm
>>>
>>> It just displays:
>>>
>>> U-Boot SPL 2017.09-00135-g8eafae2 (Sep 16 2017 - 15:23:16)
>>> Trying to boot from MMC1
>>>
>>> Then hangs.
>>>
>>> It does, however the same patch boots just fine on
>>> omap3_logic_defconfig which is an OMAP3630/DM3730 board.
>>>
>>> da850evm_defconfig (OMAP-L138) is also booting just fine.
>>>
>>> I'm going to investigate it further to see why just 1/3 boards seems impacted.
>>>
>>
>> Tom reported a similar fail.. although I am failing to reproduce it in
>> sandbox w/ a copy of his partition, so maybe it is somehow hw
>> specific?  If you could, debug logs w/
>> https://hastebin.com/raw/fijazebiso applied in before/after case would
>> be useful.. maybe I could spot something from that?
>>
>
> Adding the debug to master made no difference.  No debug messages appeared.
> Interestingly enough, some junk appeard, and the name of U-Boot name
> wasn't correctly displayed:
>
> **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
> Trying to boot from MMC1
>
> (hang)
>
> Could there a be some memory overflow somewhere?
>
> Adding the debug to the last working commit, yielded the following:
>
> U-Boot SPL 2017.09-00134-ge71f88d-dirty (Sep 17 2017 - 06:03:28)
> Trying to boot from MMC1
> reading u-boot.img
> VFAT Support enabled
> FAT16, fat_sect: 1, fatlength: 200
> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
> Data begins at: 417
> Sector size: 512, cluster size: 8
> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=d
> RootMismatch: |mlo||
> Rootvfatname: |u-boot.img|
> RootName: u-boot.img, start: 0x98, size:  0x83708
> Filesize: u bytes
> u bytes
> gc - clustnum: 152, startsect: 1633
> Size: 538376, got: u
> reading u-boot.img
> VFAT Support enabled
> FAT16, fat_sect: 1, fatlength: 200
> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
> Data begins at: 417
> Sector size: 512, cluster size: 8
> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=d
> RootMismatch: |mlo||
> Rootvfatname: |u-boot.img|
> RootName: u-boot.img, start: 0x98, size:  0x83708
> Filesize: u bytes
> u bytes
>
> I truncated it, because after that, it seems to just be showing
> entries and offsets over and over again.
>

Thanks, this first part is what I was looking for.

Not sure why DEBUG would make it hang on master.  I don't know much
about spl, but is there a way you can get it to just do 'ls mmc 1:1'
instead of loading u-boot.img?  ls should give me the same information
about the partition, without so many repeating entries/offsets.
Alternately, is it possible to boot w/ old spl image but new
u-boot.img to debug this once we get into main u-boot image??

BR,
-R
Rob Clark Sept. 17, 2017, 12:30 p.m. UTC | #7
On Sun, Sep 17, 2017 at 8:28 AM, Rob Clark <robdclark@gmail.com> wrote:
> On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
>> On Sat, Sep 16, 2017 at 3:42 PM, Rob Clark <robdclark@gmail.com> wrote:
>>> On Sat, Sep 16, 2017 at 4:32 PM, Adam Ford <aford173@gmail.com> wrote:
>>>> On Fri, Sep 15, 2017 at 9:32 PM, Tom Rini <trini@konsulko.com> wrote:
>>>>>
>>>>> On Sat, Sep 09, 2017 at 01:15:54PM -0400, Rob Clark wrote:
>>>>>
>>>>> > And drop a whole lot of ugly code!
>>>>> >
>>>>> > Signed-off-by: Rob Clark <robdclark@gmail.com>
>>>>> > Reviewed-by: Łukasz Majewski <lukma@denx.de>
>>>>> > Reviewed-by: Simon Glass <sjg@chromium.org>
>>>>>
>>>>> Applied to u-boot/master, thanks!
>>>>>
>>>>
>>>> According to git bisect, this patch seems to break the booting of am3517_evm
>>>>
>>>> It just displays:
>>>>
>>>> U-Boot SPL 2017.09-00135-g8eafae2 (Sep 16 2017 - 15:23:16)
>>>> Trying to boot from MMC1
>>>>
>>>> Then hangs.
>>>>
>>>> It does, however the same patch boots just fine on
>>>> omap3_logic_defconfig which is an OMAP3630/DM3730 board.
>>>>
>>>> da850evm_defconfig (OMAP-L138) is also booting just fine.
>>>>
>>>> I'm going to investigate it further to see why just 1/3 boards seems impacted.
>>>>
>>>
>>> Tom reported a similar fail.. although I am failing to reproduce it in
>>> sandbox w/ a copy of his partition, so maybe it is somehow hw
>>> specific?  If you could, debug logs w/
>>> https://hastebin.com/raw/fijazebiso applied in before/after case would
>>> be useful.. maybe I could spot something from that?
>>>
>>
>> Adding the debug to master made no difference.  No debug messages appeared.
>> Interestingly enough, some junk appeard, and the name of U-Boot name
>> wasn't correctly displayed:
>>
>> **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
>> Trying to boot from MMC1
>>
>> (hang)
>>
>> Could there a be some memory overflow somewhere?
>>
>> Adding the debug to the last working commit, yielded the following:
>>
>> U-Boot SPL 2017.09-00134-ge71f88d-dirty (Sep 17 2017 - 06:03:28)
>> Trying to boot from MMC1
>> reading u-boot.img
>> VFAT Support enabled
>> FAT16, fat_sect: 1, fatlength: 200
>> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
>> Data begins at: 417
>> Sector size: 512, cluster size: 8
>> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=d
>> RootMismatch: |mlo||
>> Rootvfatname: |u-boot.img|
>> RootName: u-boot.img, start: 0x98, size:  0x83708
>> Filesize: u bytes
>> u bytes
>> gc - clustnum: 152, startsect: 1633
>> Size: 538376, got: u
>> reading u-boot.img
>> VFAT Support enabled
>> FAT16, fat_sect: 1, fatlength: 200
>> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
>> Data begins at: 417
>> Sector size: 512, cluster size: 8
>> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=d
>> RootMismatch: |mlo||
>> Rootvfatname: |u-boot.img|
>> RootName: u-boot.img, start: 0x98, size:  0x83708
>> Filesize: u bytes
>> u bytes
>>
>> I truncated it, because after that, it seems to just be showing
>> entries and offsets over and over again.
>>
>
> Thanks, this first part is what I was looking for.
>
> Not sure why DEBUG would make it hang on master.  I don't know much
> about spl, but is there a way you can get it to just do 'ls mmc 1:1'
> instead of loading u-boot.img?  ls should give me the same information
> about the partition, without so many repeating entries/offsets.
> Alternately, is it possible to boot w/ old spl image but new
> u-boot.img to debug this once we get into main u-boot image??

I suppose another benefit if it is possible to use old spl and new
u-boot.img is the presumably u-boot.img isn't using TINY_PRINTF so the
debug prints about the partition parameters would be more complete..

BR,
-R
Rob Clark Sept. 17, 2017, 12:53 p.m. UTC | #8
On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
>
> Adding the debug to master made no difference.  No debug messages appeared.
> Interestingly enough, some junk appeard, and the name of U-Boot name
> wasn't correctly displayed:
>
> **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
> Trying to boot from MMC1
>
> (hang)
>

hmm, one thing I noticed in doc/README.SPL:

"When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG
as in most cases do_reset is not defined within SPL."

not sure if that would help.

Also, it has a section about estimating stack usage.. not sure if this
implies that stack size is constrained in spl?  If so, maybe that is
related.  The new directory iterators do move the buffer for current
block of dir_entry's to the stack.  Reducing
CONFIG_FS_FAT_MAX_CLUSTSIZE might help.

BR,
-R
Tom Rini Sept. 17, 2017, 1:28 p.m. UTC | #9
On Sun, Sep 17, 2017 at 08:53:23AM -0400, Rob Clark wrote:
> On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
> >
> > Adding the debug to master made no difference.  No debug messages appeared.
> > Interestingly enough, some junk appeard, and the name of U-Boot name
> > wasn't correctly displayed:
> >
> > **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
> > Trying to boot from MMC1
> >
> > (hang)
> >
> 
> hmm, one thing I noticed in doc/README.SPL:
> 
> "When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG
> as in most cases do_reset is not defined within SPL."
> 
> not sure if that would help.
> 
> Also, it has a section about estimating stack usage.. not sure if this
> implies that stack size is constrained in spl?  If so, maybe that is
> related.  The new directory iterators do move the buffer for current
> block of dir_entry's to the stack.  Reducing
> CONFIG_FS_FAT_MAX_CLUSTSIZE might help.

Yes, in SPL we don't require stack being in SDRAM and unless SPL_STACK_R
is set we have a very limited stack available.  And that looks to be the
common thread between functional and non-functional platforms.  In the
case of what Adam and I both have, we could move to SPL_STACK_R easily
enough.  What needs to be done next 'tho would be to see if making
SPL_FAT_SUPPORT depend on SPL_STACK_R, migrating the various TI
platforms (and possibly others) that could butdon't use SPL_STACK_R, and
seeing if we have platforms that have now lost FAT support.

Or, how hard would it be to make that code not use the stack so much?
Adam Ford Sept. 17, 2017, 1:42 p.m. UTC | #10
On Sun, Sep 17, 2017 at 7:53 AM, Rob Clark <robdclark@gmail.com> wrote:
> On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
>>
>> Adding the debug to master made no difference.  No debug messages appeared.
>> Interestingly enough, some junk appeard, and the name of U-Boot name
>> wasn't correctly displayed:
>>
>> **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
>> Trying to boot from MMC1
>>
>> (hang)
>>
>

With the TINY_PRINTF disabled (except in SPL),  the log looks better:

Trying to boot from MMC1
reading u-boot.img
VFAT Support enabled
FAT16, fat_sect: 1, fatlength: 200
Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
Data begins at: 417
Sector size: 512, cluster size: 8
FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
RootMismatch: |mlo||
Rootvfatname: |u-boot.img|
RootName: u-boot.img, start: 0x12, size:  0x83708
Filesize: 538376 bytes
64 bytes
gc - clustnum: 18, startsect: 561
Size: 538376, got: 64
reading u-boot.img
VFAT Support enabled
FAT16, fat_sect: 1, fatlength: 200
Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
Data begins at: 417
Sector size: 512, cluster size: 8
FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
RootMismatch: |mlo||
Rootvfatname: |u-boot.img|
RootName: u-boot.img, start: 0x12, size:  0x83708
Filesize: 538376 bytes



> hmm, one thing I noticed in doc/README.SPL:
>
> "When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG
> as in most cases do_reset is not defined within SPL."
>
> not sure if that would help.
>

I did try your experiment with keeping the working SPL and using the
newer u-boot.img file and that worked, so I am guessing it's probably
related to tight memory in SPL.
I looked up the mapping in doc/SPL/README.omap3 and it shows:

0x40200800 - 0x4020BBFF: Area for SPL text, data and rodata
0x4020E000 - 0x4020FFFC: Area for the SPL stack.
0x80000000 - 0x8007FFFF: Area for the SPL BSS.
0x80100000: CONFIG_SYS_TEXT_BASE of U-Boot
0x80208000 - 0x80307FFF: malloc() pool available to SPL.

For this board, CONFIG_SYS_SPL_MALLOC_SIZE is set to 0x100000

I don't know if any of this is helpful information to you or not.

> Also, it has a section about estimating stack usage.. not sure if this
> implies that stack size is constrained in spl?  If so, maybe that is
> related.  The new directory iterators do move the buffer for current
> block of dir_entry's to the stack.  Reducing
> CONFIG_FS_FAT_MAX_CLUSTSIZE might help.

Any recommendations on how small this can go and still operate
reliably?  I don't want to just arbitrarily choose something.

>
> BR,
> -R

adam
Rob Clark Sept. 17, 2017, 1:50 p.m. UTC | #11
On Sun, Sep 17, 2017 at 9:42 AM, Adam Ford <aford173@gmail.com> wrote:
> On Sun, Sep 17, 2017 at 7:53 AM, Rob Clark <robdclark@gmail.com> wrote:
>> On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
>>>
>>> Adding the debug to master made no difference.  No debug messages appeared.
>>> Interestingly enough, some junk appeard, and the name of U-Boot name
>>> wasn't correctly displayed:
>>>
>>> **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
>>> Trying to boot from MMC1
>>>
>>> (hang)
>>>
>>
>
> With the TINY_PRINTF disabled (except in SPL),  the log looks better:
>
> Trying to boot from MMC1
> reading u-boot.img
> VFAT Support enabled
> FAT16, fat_sect: 1, fatlength: 200
> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
> Data begins at: 417
> Sector size: 512, cluster size: 8
> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
> RootMismatch: |mlo||
> Rootvfatname: |u-boot.img|
> RootName: u-boot.img, start: 0x12, size:  0x83708
> Filesize: 538376 bytes
> 64 bytes
> gc - clustnum: 18, startsect: 561
> Size: 538376, got: 64
> reading u-boot.img
> VFAT Support enabled
> FAT16, fat_sect: 1, fatlength: 200
> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
> Data begins at: 417
> Sector size: 512, cluster size: 8
> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
> RootMismatch: |mlo||
> Rootvfatname: |u-boot.img|
> RootName: u-boot.img, start: 0x12, size:  0x83708
> Filesize: 538376 bytes
>
>
>
>> hmm, one thing I noticed in doc/README.SPL:
>>
>> "When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG
>> as in most cases do_reset is not defined within SPL."
>>
>> not sure if that would help.
>>
>
> I did try your experiment with keeping the working SPL and using the
> newer u-boot.img file and that worked, so I am guessing it's probably
> related to tight memory in SPL.
> I looked up the mapping in doc/SPL/README.omap3 and it shows:
>
> 0x40200800 - 0x4020BBFF: Area for SPL text, data and rodata
> 0x4020E000 - 0x4020FFFC: Area for the SPL stack.
> 0x80000000 - 0x8007FFFF: Area for the SPL BSS.
> 0x80100000: CONFIG_SYS_TEXT_BASE of U-Boot
> 0x80208000 - 0x80307FFF: malloc() pool available to SPL.
>
> For this board, CONFIG_SYS_SPL_MALLOC_SIZE is set to 0x100000
>
> I don't know if any of this is helpful information to you or not.

I think we narrowed it down to stack usage.. Tom tested the "please
test" patch I just sent and it works for him.

If reducing SPL_MALLOC_SIZE increases available stack size, that might
also work.  But I think for next release we can just go with my patch
that moves itrblock off the stack.

>> Also, it has a section about estimating stack usage.. not sure if this
>> implies that stack size is constrained in spl?  If so, maybe that is
>> related.  The new directory iterators do move the buffer for current
>> block of dir_entry's to the stack.  Reducing
>> CONFIG_FS_FAT_MAX_CLUSTSIZE might help.
>
> Any recommendations on how small this can go and still operate
> reliably?  I don't want to just arbitrarily choose something.


Sector size: 512, cluster size: 8
FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16

So I think 512 * 8 = 4096 would work for your filesys.. what I'm not
entirely sure is what range of sector sizes and cluster sizes are
possible.  64k seems *way* too much.  Maybe in the end I should switch
to malloc() so we can allocate just what is needed.

I'll give it some thought for my next batch of fs/fat work.. but
suggestions welcome.

BR,
-R
Adam Ford Sept. 17, 2017, 1:52 p.m. UTC | #12
On Sun, Sep 17, 2017 at 8:50 AM, Rob Clark <robdclark@gmail.com> wrote:
> On Sun, Sep 17, 2017 at 9:42 AM, Adam Ford <aford173@gmail.com> wrote:
>> On Sun, Sep 17, 2017 at 7:53 AM, Rob Clark <robdclark@gmail.com> wrote:
>>> On Sun, Sep 17, 2017 at 7:08 AM, Adam Ford <aford173@gmail.com> wrote:
>>>>
>>>> Adding the debug to master made no difference.  No debug messages appeared.
>>>> Interestingly enough, some junk appeard, and the name of U-Boot name
>>>> wasn't correctly displayed:
>>>>
>>>> **Sș017.09-00178-g08cebee-dirty (Sep 17 2017 - 06:01:07)
>>>> Trying to boot from MMC1
>>>>
>>>> (hang)
>>>>
>>>
>>
>> With the TINY_PRINTF disabled (except in SPL),  the log looks better:
>>
>> Trying to boot from MMC1
>> reading u-boot.img
>> VFAT Support enabled
>> FAT16, fat_sect: 1, fatlength: 200
>> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
>> Data begins at: 417
>> Sector size: 512, cluster size: 8
>> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
>> RootMismatch: |mlo||
>> Rootvfatname: |u-boot.img|
>> RootName: u-boot.img, start: 0x12, size:  0x83708
>> Filesize: 538376 bytes
>> 64 bytes
>> gc - clustnum: 18, startsect: 561
>> Size: 538376, got: 64
>> reading u-boot.img
>> VFAT Support enabled
>> FAT16, fat_sect: 1, fatlength: 200
>> Rootdir begins at cluster: 536870910, sector: 401, offset: 32200
>> Data begins at: 417
>> Sector size: 512, cluster size: 8
>> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
>> RootMismatch: |mlo||
>> Rootvfatname: |u-boot.img|
>> RootName: u-boot.img, start: 0x12, size:  0x83708
>> Filesize: 538376 bytes
>>
>>
>>
>>> hmm, one thing I noticed in doc/README.SPL:
>>>
>>> "When building SPL with DEBUG set you may also need to set CONFIG_PANIC_HANG
>>> as in most cases do_reset is not defined within SPL."
>>>
>>> not sure if that would help.
>>>
>>
>> I did try your experiment with keeping the working SPL and using the
>> newer u-boot.img file and that worked, so I am guessing it's probably
>> related to tight memory in SPL.
>> I looked up the mapping in doc/SPL/README.omap3 and it shows:
>>
>> 0x40200800 - 0x4020BBFF: Area for SPL text, data and rodata
>> 0x4020E000 - 0x4020FFFC: Area for the SPL stack.
>> 0x80000000 - 0x8007FFFF: Area for the SPL BSS.
>> 0x80100000: CONFIG_SYS_TEXT_BASE of U-Boot
>> 0x80208000 - 0x80307FFF: malloc() pool available to SPL.
>>
>> For this board, CONFIG_SYS_SPL_MALLOC_SIZE is set to 0x100000
>>
>> I don't know if any of this is helpful information to you or not.
>
> I think we narrowed it down to stack usage.. Tom tested the "please
> test" patch I just sent and it works for him.
>
> If reducing SPL_MALLOC_SIZE increases available stack size, that might
> also work.  But I think for next release we can just go with my patch
> that moves itrblock off the stack.
>
>>> Also, it has a section about estimating stack usage.. not sure if this
>>> implies that stack size is constrained in spl?  If so, maybe that is
>>> related.  The new directory iterators do move the buffer for current
>>> block of dir_entry's to the stack.  Reducing
>>> CONFIG_FS_FAT_MAX_CLUSTSIZE might help.
>>
>> Any recommendations on how small this can go and still operate
>> reliably?  I don't want to just arbitrarily choose something.
>
>
> Sector size: 512, cluster size: 8
> FAT read(sect=401, cnt:2), clust_size=8, DIRENTSPERBLOCK=16
>
> So I think 512 * 8 = 4096 would work for your filesys.. what I'm not
> entirely sure is what range of sector sizes and cluster sizes are
> possible.  64k seems *way* too much.  Maybe in the end I should switch
> to malloc() so we can allocate just what is needed.
>
> I'll give it some thought for my next batch of fs/fat work.. but
> suggestions welcome.
>

When I wrote that, I didn't see either Tom's comments or you updated
patch yet, but you can go ahead and add my tested-by because I'm
satisfied with that.

adam
> BR,
> -R
diff mbox series

Patch

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index ee2bbe38f1..bbba7947ee 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -119,22 +119,6 @@  int fat_register_device(struct blk_desc *dev_desc, int part_no)
 }
 
 /*
- * Get the first occurence of a directory delimiter ('/' or '\') in a string.
- * Return index into string if found, -1 otherwise.
- */
-static int dirdelim(char *str)
-{
-	char *start = str;
-
-	while (*str != '\0') {
-		if (ISDIRDELIM(*str))
-			return str - start;
-		str++;
-	}
-	return -1;
-}
-
-/*
  * Extract zero terminated short name from a directory entry.
  */
 static void get_name(dir_entry *dirent, char *s_name)
@@ -468,95 +452,6 @@  static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
 	return 0;
 }
 
-/*
- * Extract the full long filename starting at 'retdent' (which is really
- * a slot) into 'l_name'. If successful also copy the real directory entry
- * into 'retdent'
- * Return 0 on success, -1 otherwise.
- */
-static int
-get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
-	     dir_entry *retdent, char *l_name)
-{
-	dir_entry *realdent;
-	dir_slot *slotptr = (dir_slot *)retdent;
-	__u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ?
-							PREFETCH_BLOCKS :
-							mydata->clust_size);
-	__u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
-	int idx = 0;
-
-	if (counter > VFAT_MAXSEQ) {
-		debug("Error: VFAT name is too long\n");
-		return -1;
-	}
-
-	while ((__u8 *)slotptr < buflimit) {
-		if (counter == 0)
-			break;
-		if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
-			return -1;
-		slotptr++;
-		counter--;
-	}
-
-	if ((__u8 *)slotptr >= buflimit) {
-		dir_slot *slotptr2;
-
-		if (curclust == 0)
-			return -1;
-		curclust = get_fatent(mydata, curclust);
-		if (CHECK_CLUST(curclust, mydata->fatsize)) {
-			debug("curclust: 0x%x\n", curclust);
-			printf("Invalid FAT entry\n");
-			return -1;
-		}
-
-		if (get_cluster(mydata, curclust, get_contents_vfatname_block,
-				mydata->clust_size * mydata->sect_size) != 0) {
-			debug("Error: reading directory block\n");
-			return -1;
-		}
-
-		slotptr2 = (dir_slot *)get_contents_vfatname_block;
-		while (counter > 0) {
-			if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
-			    & 0xff) != counter)
-				return -1;
-			slotptr2++;
-			counter--;
-		}
-
-		/* Save the real directory entry */
-		realdent = (dir_entry *)slotptr2;
-		while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
-			slotptr2--;
-			slot2str(slotptr2, l_name, &idx);
-		}
-	} else {
-		/* Save the real directory entry */
-		realdent = (dir_entry *)slotptr;
-	}
-
-	do {
-		slotptr--;
-		if (slot2str(slotptr, l_name, &idx))
-			break;
-	} while (!(slotptr->id & LAST_LONG_ENTRY_MASK));
-
-	l_name[idx] = '\0';
-	if (*l_name == DELETED_FLAG)
-		*l_name = '\0';
-	else if (*l_name == aRING)
-		*l_name = DELETED_FLAG;
-	downcase(l_name);
-
-	/* Return the real directory entry */
-	memcpy(retdent, realdent, sizeof(dir_entry));
-
-	return 0;
-}
-
 /* Calculate short name checksum */
 static __u8 mkcksum(const char name[8], const char ext[3])
 {
@@ -573,169 +468,13 @@  static __u8 mkcksum(const char name[8], const char ext[3])
 }
 
 /*
- * Get the directory entry associated with 'filename' from the directory
- * starting at 'startsect'
+ * TODO these should go away once fat_write is reworked to use the
+ * directory iterator
  */
 __u8 get_dentfromdir_block[MAX_CLUSTSIZE]
 	__aligned(ARCH_DMA_MINALIGN);
-
-static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
-				  char *filename, dir_entry *retdent,
-				  int dols)
-{
-	__u16 prevcksum = 0xffff;
-	__u32 curclust = START(retdent);
-	int files = 0, dirs = 0;
-
-	debug("get_dentfromdir: %s\n", filename);
-
-	while (1) {
-		dir_entry *dentptr;
-
-		int i;
-
-		if (get_cluster(mydata, curclust, get_dentfromdir_block,
-				mydata->clust_size * mydata->sect_size) != 0) {
-			debug("Error: reading directory block\n");
-			return NULL;
-		}
-
-		dentptr = (dir_entry *)get_dentfromdir_block;
-
-		for (i = 0; i < DIRENTSPERCLUST; i++) {
-			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
-
-			l_name[0] = '\0';
-			if (dentptr->name[0] == DELETED_FLAG) {
-				dentptr++;
-				continue;
-			}
-			if ((dentptr->attr & ATTR_VOLUME)) {
-				if (vfat_enabled &&
-				    (dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
-				    (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
-					prevcksum = ((dir_slot *)dentptr)->alias_checksum;
-					get_vfatname(mydata, curclust,
-						     get_dentfromdir_block,
-						     dentptr, l_name);
-					if (dols) {
-						int isdir;
-						char dirc;
-						int doit = 0;
-
-						isdir = (dentptr->attr & ATTR_DIR);
-
-						if (isdir) {
-							dirs++;
-							dirc = '/';
-							doit = 1;
-						} else {
-							dirc = ' ';
-							if (l_name[0] != 0) {
-								files++;
-								doit = 1;
-							}
-						}
-						if (doit) {
-							if (dirc == ' ') {
-								printf(" %8u   %s%c\n",
-								       FAT2CPU32(dentptr->size),
-									l_name,
-									dirc);
-							} else {
-								printf("            %s%c\n",
-									l_name,
-									dirc);
-							}
-						}
-						dentptr++;
-						continue;
-					}
-					debug("vfatname: |%s|\n", l_name);
-				} else {
-					/* Volume label or VFAT entry */
-					dentptr++;
-					continue;
-				}
-			}
-			if (dentptr->name[0] == 0) {
-				if (dols) {
-					printf("\n%d file(s), %d dir(s)\n\n",
-						files, dirs);
-				}
-				debug("Dentname == NULL - %d\n", i);
-				return NULL;
-			}
-			if (vfat_enabled) {
-				__u8 csum = mkcksum(dentptr->name, dentptr->ext);
-				if (dols && csum == prevcksum) {
-					prevcksum = 0xffff;
-					dentptr++;
-					continue;
-				}
-			}
-
-			get_name(dentptr, s_name);
-			if (dols) {
-				int isdir = (dentptr->attr & ATTR_DIR);
-				char dirc;
-				int doit = 0;
-
-				if (isdir) {
-					dirs++;
-					dirc = '/';
-					doit = 1;
-				} else {
-					dirc = ' ';
-					if (s_name[0] != 0) {
-						files++;
-						doit = 1;
-					}
-				}
-
-				if (doit) {
-					if (dirc == ' ') {
-						printf(" %8u   %s%c\n",
-						       FAT2CPU32(dentptr->size),
-							s_name, dirc);
-					} else {
-						printf("            %s%c\n",
-							s_name, dirc);
-					}
-				}
-
-				dentptr++;
-				continue;
-			}
-
-			if (strcmp(filename, s_name)
-			    && strcmp(filename, l_name)) {
-				debug("Mismatch: |%s|%s|\n", s_name, l_name);
-				dentptr++;
-				continue;
-			}
-
-			memcpy(retdent, dentptr, sizeof(dir_entry));
-
-			debug("DentName: %s", s_name);
-			debug(", start: 0x%x", START(dentptr));
-			debug(", size:  0x%x %s\n",
-			      FAT2CPU32(dentptr->size),
-			      (dentptr->attr & ATTR_DIR) ? "(DIR)" : "");
-
-			return retdent;
-		}
-
-		curclust = get_fatent(mydata, curclust);
-		if (CHECK_CLUST(curclust, mydata->fatsize)) {
-			debug("curclust: 0x%x\n", curclust);
-			printf("Invalid FAT entry\n");
-			return NULL;
-		}
-	}
-
-	return NULL;
-}
+__u8 do_fat_read_at_block[MAX_CLUSTSIZE]
+	__aligned(ARCH_DMA_MINALIGN);
 
 /*
  * Read boot sector and volume info from a FAT filesystem
@@ -879,374 +618,6 @@  static int get_fs_info(fsdata *mydata)
 	return 0;
 }
 
-__u8 do_fat_read_at_block[MAX_CLUSTSIZE]
-	__aligned(ARCH_DMA_MINALIGN);
-
-int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
-		   loff_t maxsize, int dols, int dogetsize, loff_t *size)
-{
-	char fnamecopy[2048];
-	fsdata datablock;
-	fsdata *mydata = &datablock;
-	dir_entry *dentptr = NULL;
-	__u16 prevcksum = 0xffff;
-	char *subname = "";
-	__u32 cursect;
-	int idx, isdir = 0;
-	int files = 0, dirs = 0;
-	int ret = -1;
-	int firsttime;
-	__u32 root_cluster = 0;
-	__u32 read_blk;
-	int rootdir_size = 0;
-	int buffer_blk_cnt;
-	int do_read;
-	__u8 *dir_ptr;
-
-	if (get_fs_info(mydata))
-		return -1;
-
-	cursect = mydata->rootdir_sect;
-
-	/* "cwd" is always the root... */
-	while (ISDIRDELIM(*filename))
-		filename++;
-
-	/* Make a copy of the filename and convert it to lowercase */
-	strcpy(fnamecopy, filename);
-	downcase(fnamecopy);
-
-root_reparse:
-	if (*fnamecopy == '\0') {
-		if (!dols)
-			goto exit;
-
-		dols = LS_ROOT;
-	} else if ((idx = dirdelim(fnamecopy)) >= 0) {
-		isdir = 1;
-		fnamecopy[idx] = '\0';
-		subname = fnamecopy + idx + 1;
-
-		/* Handle multiple delimiters */
-		while (ISDIRDELIM(*subname))
-			subname++;
-	} else if (dols) {
-		isdir = 1;
-	}
-
-	buffer_blk_cnt = 0;
-	firsttime = 1;
-	while (1) {
-		int i;
-
-		if (mydata->fatsize == 32 || firsttime) {
-			dir_ptr = do_fat_read_at_block;
-			firsttime = 0;
-		} else {
-			/**
-			 * FAT16 sector buffer modification:
-			 * Each loop, the second buffered block is moved to
-			 * the buffer begin, and two next sectors are read
-			 * next to the previously moved one. So the sector
-			 * buffer keeps always 3 sectors for fat16.
-			 * And the current sector is the buffer second sector
-			 * beside the "firsttime" read, when it is the first one.
-			 *
-			 * PREFETCH_BLOCKS is 2 for FAT16 == loop[0:1]
-			 * n = computed root dir sector
-			 * loop |  cursect-1  | cursect    | cursect+1  |
-			 *   0  |  sector n+0 | sector n+1 | none       |
-			 *   1  |  none       | sector n+0 | sector n+1 |
-			 *   0  |  sector n+1 | sector n+2 | sector n+3 |
-			 *   1  |  sector n+3 | ...
-			*/
-			dir_ptr = (do_fat_read_at_block + mydata->sect_size);
-			memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
-		}
-
-		do_read = 1;
-
-		if (mydata->fatsize == 32 && buffer_blk_cnt)
-			do_read = 0;
-
-		if (do_read) {
-			read_blk = (mydata->fatsize == 32) ?
-				    mydata->clust_size : PREFETCH_BLOCKS;
-
-			debug("FAT read(sect=%d, cnt:%d), clust_size=%d, DIRENTSPERBLOCK=%zd\n",
-				cursect, read_blk, mydata->clust_size, DIRENTSPERBLOCK);
-
-			if (disk_read(cursect, read_blk, dir_ptr) < 0) {
-				debug("Error: reading rootdir block\n");
-				goto exit;
-			}
-
-			dentptr = (dir_entry *)dir_ptr;
-		}
-
-		for (i = 0; i < DIRENTSPERBLOCK; i++) {
-			char s_name[14], l_name[VFAT_MAXLEN_BYTES];
-			__u8 csum;
-
-			l_name[0] = '\0';
-			if (dentptr->name[0] == DELETED_FLAG) {
-				dentptr++;
-				continue;
-			}
-
-			if (vfat_enabled)
-				csum = mkcksum(dentptr->name, dentptr->ext);
-
-			if (dentptr->attr & ATTR_VOLUME) {
-				if (vfat_enabled &&
-				    (dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
-				    (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
-					prevcksum =
-						((dir_slot *)dentptr)->alias_checksum;
-
-					get_vfatname(mydata,
-						     root_cluster,
-						     dir_ptr,
-						     dentptr, l_name);
-
-					if (dols == LS_ROOT) {
-						char dirc;
-						int doit = 0;
-						int isdir =
-							(dentptr->attr & ATTR_DIR);
-
-						if (isdir) {
-							dirs++;
-							dirc = '/';
-							doit = 1;
-						} else {
-							dirc = ' ';
-							if (l_name[0] != 0) {
-								files++;
-								doit = 1;
-							}
-						}
-						if (doit) {
-							if (dirc == ' ') {
-								printf(" %8u   %s%c\n",
-								       FAT2CPU32(dentptr->size),
-									l_name,
-									dirc);
-							} else {
-								printf("            %s%c\n",
-									l_name,
-									dirc);
-							}
-						}
-						dentptr++;
-						continue;
-					}
-					debug("Rootvfatname: |%s|\n",
-					       l_name);
-				} else {
-					/* Volume label or VFAT entry */
-					dentptr++;
-					continue;
-				}
-			} else if (dentptr->name[0] == 0) {
-				debug("RootDentname == NULL - %d\n", i);
-				if (dols == LS_ROOT) {
-					printf("\n%d file(s), %d dir(s)\n\n",
-						files, dirs);
-					ret = 0;
-				}
-				goto exit;
-			}
-			else if (vfat_enabled &&
-				 dols == LS_ROOT && csum == prevcksum) {
-				prevcksum = 0xffff;
-				dentptr++;
-				continue;
-			}
-
-			get_name(dentptr, s_name);
-
-			if (dols == LS_ROOT) {
-				int isdir = (dentptr->attr & ATTR_DIR);
-				char dirc;
-				int doit = 0;
-
-				if (isdir) {
-					dirc = '/';
-					if (s_name[0] != 0) {
-						dirs++;
-						doit = 1;
-					}
-				} else {
-					dirc = ' ';
-					if (s_name[0] != 0) {
-						files++;
-						doit = 1;
-					}
-				}
-				if (doit) {
-					if (dirc == ' ') {
-						printf(" %8u   %s%c\n",
-						       FAT2CPU32(dentptr->size),
-							s_name, dirc);
-					} else {
-						printf("            %s%c\n",
-							s_name, dirc);
-					}
-				}
-				dentptr++;
-				continue;
-			}
-
-			if (strcmp(fnamecopy, s_name)
-			    && strcmp(fnamecopy, l_name)) {
-				debug("RootMismatch: |%s|%s|\n", s_name,
-				       l_name);
-				dentptr++;
-				continue;
-			}
-
-			if (isdir && !(dentptr->attr & ATTR_DIR))
-				goto exit;
-
-			debug("RootName: %s", s_name);
-			debug(", start: 0x%x", START(dentptr));
-			debug(", size:  0x%x %s\n",
-			       FAT2CPU32(dentptr->size),
-			       isdir ? "(DIR)" : "");
-
-			goto rootdir_done;	/* We got a match */
-		}
-		debug("END LOOP: buffer_blk_cnt=%d   clust_size=%d\n", buffer_blk_cnt,
-		       mydata->clust_size);
-
-		/*
-		 * On FAT32 we must fetch the FAT entries for the next
-		 * root directory clusters when a cluster has been
-		 * completely processed.
-		 */
-		++buffer_blk_cnt;
-		int rootdir_end = 0;
-		if (mydata->fatsize == 32) {
-			if (buffer_blk_cnt == mydata->clust_size) {
-				int nxtsect = 0;
-				int nxt_clust = 0;
-
-				nxt_clust = get_fatent(mydata, root_cluster);
-				rootdir_end = CHECK_CLUST(nxt_clust, 32);
-
-				nxtsect = mydata->data_begin +
-					(nxt_clust * mydata->clust_size);
-
-				root_cluster = nxt_clust;
-
-				cursect = nxtsect;
-				buffer_blk_cnt = 0;
-			}
-		} else {
-			if (buffer_blk_cnt == PREFETCH_BLOCKS)
-				buffer_blk_cnt = 0;
-
-			rootdir_end = (++cursect - mydata->rootdir_sect >=
-				       rootdir_size);
-		}
-
-		/* If end of rootdir reached */
-		if (rootdir_end) {
-			if (dols == LS_ROOT) {
-				printf("\n%d file(s), %d dir(s)\n\n",
-				       files, dirs);
-				*size = 0;
-			}
-			goto exit;
-		}
-	}
-rootdir_done:
-
-	firsttime = 1;
-
-	while (isdir) {
-		int startsect = mydata->data_begin
-			+ START(dentptr) * mydata->clust_size;
-		dir_entry dent;
-		char *nextname = NULL;
-
-		dent = *dentptr;
-		dentptr = &dent;
-
-		idx = dirdelim(subname);
-
-		if (idx >= 0) {
-			subname[idx] = '\0';
-			nextname = subname + idx + 1;
-			/* Handle multiple delimiters */
-			while (ISDIRDELIM(*nextname))
-				nextname++;
-			if (dols && *nextname == '\0')
-				firsttime = 0;
-		} else {
-			if (dols && firsttime) {
-				firsttime = 0;
-			} else {
-				isdir = 0;
-			}
-		}
-
-		if (get_dentfromdir(mydata, startsect, subname, dentptr,
-				     isdir ? 0 : dols) == NULL) {
-			if (dols && !isdir)
-				*size = 0;
-			goto exit;
-		}
-
-		if (isdir && !(dentptr->attr & ATTR_DIR))
-			goto exit;
-
-		/*
-		 * If we are looking for a directory, and found a directory
-		 * type entry, and the entry is for the root directory (as
-		 * denoted by a cluster number of 0), jump back to the start
-		 * of the function, since at least on FAT12/16, the root dir
-		 * lives in a hard-coded location and needs special handling
-		 * to parse, rather than simply following the cluster linked
-		 * list in the FAT, like other directories.
-		 */
-		if (isdir && (dentptr->attr & ATTR_DIR) && !START(dentptr)) {
-			/*
-			 * Modify the filename to remove the prefix that gets
-			 * back to the root directory, so the initial root dir
-			 * parsing code can continue from where we are without
-			 * confusion.
-			 */
-			strcpy(fnamecopy, nextname ?: "");
-			/*
-			 * Set up state the same way as the function does when
-			 * first started. This is required for the root dir
-			 * parsing code operates in its expected environment.
-			 */
-			subname = "";
-			cursect = mydata->rootdir_sect;
-			isdir = 0;
-			goto root_reparse;
-		}
-
-		if (idx >= 0)
-			subname = nextname;
-	}
-
-	if (dogetsize) {
-		*size = FAT2CPU32(dentptr->size);
-		ret = 0;
-	} else {
-		ret = get_contents(mydata, dentptr, pos, buffer, maxsize, size);
-	}
-	debug("Size: %u, got: %llu\n", FAT2CPU32(dentptr->size), *size);
-
-exit:
-	free(mydata->fatbuf);
-	return ret;
-}
-
 
 /*
  * Directory iterator, to simplify filesystem traversal
@@ -1595,12 +966,6 @@  static int fat_itr_resolve(fat_itr *itr, const char *path, unsigned type)
 	return -ENOENT;
 }
 
-int do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols,
-		loff_t *actread)
-{
-	return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0, actread);
-}
-
 int file_fat_detectfs(void)
 {
 	boot_sector bs;
@@ -1665,31 +1030,96 @@  int file_fat_detectfs(void)
 
 int file_fat_ls(const char *dir)
 {
-	loff_t size;
+	fsdata fsdata;
+	fat_itr itrblock, *itr = &itrblock;
+	int files = 0, dirs = 0;
+	int ret;
+
+	ret = fat_itr_root(itr, &fsdata);
+	if (ret)
+		return ret;
+
+	ret = fat_itr_resolve(itr, dir, TYPE_DIR);
+	if (ret)
+		return ret;
+
+	while (fat_itr_next(itr)) {
+		if (fat_itr_isdir(itr)) {
+			printf("            %s/\n", itr->name);
+			dirs++;
+		} else {
+			printf(" %8u   %s\n",
+			       FAT2CPU32(itr->dent->size),
+			       itr->name);
+			files++;
+		}
+	}
 
-	return do_fat_read(dir, NULL, 0, LS_YES, &size);
+	printf("\n%d file(s), %d dir(s)\n\n", files, dirs);
+
+	return 0;
 }
 
 int fat_exists(const char *filename)
 {
+	fsdata fsdata;
+	fat_itr itrblock, *itr = &itrblock;
 	int ret;
-	loff_t size;
 
-	ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size);
+	ret = fat_itr_root(itr, &fsdata);
+	if (ret)
+		return 0;
+
+	ret = fat_itr_resolve(itr, filename, TYPE_ANY);
 	return ret == 0;
 }
 
 int fat_size(const char *filename, loff_t *size)
 {
-	return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, size);
+	fsdata fsdata;
+	fat_itr itrblock, *itr = &itrblock;
+	int ret;
+
+	ret = fat_itr_root(itr, &fsdata);
+	if (ret)
+		return ret;
+
+	ret = fat_itr_resolve(itr, filename, TYPE_FILE);
+	if (ret) {
+		/*
+		 * Directories don't have size, but fs_size() is not
+		 * expected to fail if passed a directory path:
+		 */
+		fat_itr_root(itr, &fsdata);
+		if (!fat_itr_resolve(itr, filename, TYPE_DIR)) {
+			*size = 0;
+			return 0;
+		}
+		return ret;
+	}
+
+	*size = FAT2CPU32(itr->dent->size);
+
+	return 0;
 }
 
 int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
 		     loff_t maxsize, loff_t *actread)
 {
+	fsdata fsdata;
+	fat_itr itrblock, *itr = &itrblock;
+	int ret;
+
+	ret = fat_itr_root(itr, &fsdata);
+	if (ret)
+		return ret;
+
+	ret = fat_itr_resolve(itr, filename, TYPE_FILE);
+	if (ret)
+		return ret;
+
 	printf("reading %s\n", filename);
-	return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0,
-			      actread);
+	return get_contents(&fsdata, itr->dent, pos, buffer, maxsize, actread);
 }
 
 int file_fat_read(const char *filename, void *buffer, int maxsize)
diff --git a/include/fat.h b/include/fat.h
index 21bb6666cf..18d8981c48 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -58,12 +58,6 @@ 
  */
 #define LAST_LONG_ENTRY_MASK	0x40
 
-/* Flags telling whether we should read a file or list a directory */
-#define LS_NO		0
-#define LS_YES		1
-#define LS_DIR		1
-#define LS_ROOT		2
-
 #define ISDIRDELIM(c)	((c) == '/' || (c) == '\\')
 
 #define FSTYPE_NONE	(-1)