[PATCH 1/1] fs: fix smh_fs_read_at()

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Fri Jun 2 18:21:13 CEST 2023


On 6/2/23 17:56, Sean Anderson wrote:
> On 6/2/23 04:48, Heinrich Schuchardt wrote:
>>
>>
>> On 5/18/23 17:17, Sean Anderson wrote:
>>> On 5/17/23 06:23, Heinrich Schuchardt wrote:
>>>> The return value of smh_flen() is written to size and not to ret. But ret
>>>> is checked. We can avoid calling smh_flen() by setting maxsize to LONG_MAX
>>>> if it is not set yet.
>>>>
>>>> Check input parameters.
>>>>
>>>> Fixes: f676b45151c3 ("fs: Add semihosting filesystem")
>>>> Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
>>>> ---
>>>>    fs/semihostingfs.c | 14 +++++---------
>>>>    1 file changed, 5 insertions(+), 9 deletions(-)
>>>>
>>>> diff --git a/fs/semihostingfs.c b/fs/semihostingfs.c
>>>> index 96eb3349a2..8a7d4da884 100644
>>>> --- a/fs/semihostingfs.c
>>>> +++ b/fs/semihostingfs.c
>>>> @@ -25,6 +25,9 @@ static int smh_fs_read_at(const char *filename, loff_t pos, void *buffer,
>>>>    {
>>>>        long fd, size, ret;
>>>>    +    if (pos > LONG_MAX || maxsize > LONG_MAX)
>>>
>>> Should be ULONG_MAX. The type should really be ulong but isn't.
>>>
>>>> +        return -EINVAL;
>>>> +
>>>>        fd = smh_open(filename, MODE_READ | MODE_BINARY);
>>>>        if (fd < 0)
>>>>            return fd;
>>>> @@ -33,15 +36,8 @@ static int smh_fs_read_at(const char *filename, loff_t pos, void *buffer,
>>>>            smh_close(fd);
>>>>            return ret;
>>>>        }
>>>> -    if (!maxsize) {
>>>> -        size = smh_flen(fd);
>>>> -        if (ret < 0) {
>>>> -            smh_close(fd);
>>>> -            return size;
>>>> -        }
>>>> -
>>>> -        maxsize = size;
>>>> -    }
>>>> +    if (!maxsize)
>>>> +        maxsize = LONG_MAX;
>>>
>>> Same here.
>>>
>>>>          size = smh_read(fd, buffer, maxsize);
>>
>> Thanks for reviewing.
>>
>> Just changing to ULONG_MAX will not work, because smh_read() returns errors as negative numbers.
>>
>> We would need to change the interface of smh_read to:
>>
>> int smh_read(long fd, void *memp, unsigned long *len)
>>
>> Then we could return the error code and the number of bytes read separately.
> 
> Sounds reasonable.
> 
>> https://cas5-0-urlprotect.trendmicro.com:443/wis/clicktime/v1/query?url=https%3a%2f%2fdeveloper.arm.com%2fdocumentation%2fdui0471%2fm%2fwhat%2dis%2dsemihosting%2d%2fsys%2dread%2d%2d0x06%2d&umid=985b6a56-4e08-43b2-84c0-f256a70807de&auth=d807158c60b7d2502abde8a2fc01f40662980862-076ac538dd94fd766377877ad7a42d77df41830f
>> describes that SYS_READ may return less bytes than requested. This does not signify that EOF has been reached but may simply reflect the behavior of the underlying operating system (cf. 'man 2 read').
>>> So shouldn't we loop here until all bytes are read?
> 
> We return the number of bytes read. It's up to the caller to loop if they want.
> 
> IMO for efficiency, the host should handle short reads to avoid multiple semihosting calls.

Have a look at the QEMU code. host_read() calls read() once. So if the 
underlying host file system does not read all bytes in the first 
invocation (which is allowable), SYS_READ will not do so either.

U-Boot's do_load() calls _fs_read() only once. It expects the 
semihosting filesystem to return the complete file.

So there seems to be a gap in U-Boot's semihosting code.

Best regards

Heinrich


> 
> --Sean
> 



More information about the U-Boot mailing list