Filesystems that are null_dev_desc_ok (semihosting, ubifs) have no UCLASS_BLK device under their ifname, so on real hardware fs_set_blk_dev() always fails at the partition lookup. The workaround was to add a per-filesystem command (example cmd/ubifs.c), which duplicates the plumbing of fstype_info.
Probe such entries with block_desc=NULL up front, so load semihosting <addr> <file> works without a new command. Sandbox boards that exercise the existing fallback through "host bind" stay unchanged. Signed-off-by: Vincent Jardin <[email protected]> --- Changes in v3: - Apply Simon Glass's v1 review: * Fix typo "thue" -> "the" in the commit body * Refactor the dispatch loop with a fs_lookup_null_dev_info() helper - Add doc/usage/cmd/load.rst "Null-block-device interfaces" - Add pytest regression tests for the `semihosting` and sandbox ifnames, verified passing on qemu_arm64 (with CONFIG_SEMIHOSTING=y) and on a sandbox build respectively. A ubifs test is intentionally not done. Changes in v2: - (v2 is my local iteration, not good for the list; the changes since v1 are captured in the v3 changelog below.) fs/fs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/fs/fs.c b/fs/fs.c index 8ea50a6c13c..56f3e0c9204 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -459,11 +459,53 @@ const char *fs_get_type_name(void) return fs_get_info(fs_type)->name; } +/* + * Some fstypes (semihosting, ubifs) have no underlying block device + * and ignore the block_desc argument of their probe hook. The legacy + * commands (ubifsload, semihosting via env macros) just pass NULL; + * for "load <iface> ..." to behave the same, the dispatcher opts + * those fstypes in by name here, before any block-device lookup is + * attempted. + * + * Returns the matching fstype_info if @ifname names a fstype that + * opts into null_dev_desc_ok dispatch and the caller's @fstype filter + * permits it. Returns NULL otherwise. + */ +static struct fstype_info *fs_lookup_null_dev_info(const char *ifname, + int fstype) +{ + struct fstype_info *info; + int i; + + for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) { + if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY && + fstype != info->fstype) + continue; + if (!info->null_dev_desc_ok || !info->name) + continue; + if (!strcmp(info->name, ifname)) + return info; + } + + return NULL; +} + int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) { struct fstype_info *info; int part, i; + info = fs_lookup_null_dev_info(ifname, fstype); + if (info) { + fs_dev_desc = NULL; + memset(&fs_partition, 0, sizeof(fs_partition)); + if (!info->probe(NULL, &fs_partition)) { + fs_type = info->fstype; + fs_dev_part = 0; + return 0; + } + } + part = part_get_info_by_dev_and_name_or_num(ifname, dev_part_str, &fs_dev_desc, &fs_partition, 1); if (part < 0) -- 2.43.0

