]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
fs: dispatch null_dev_desc_ok filesystems before lookup
authorVincent Jardin <vjardin@free.fr>
Wed, 15 Jul 2026 16:57:15 +0000 (18:57 +0200)
committerTom Rini <trini@konsulko.com>
Mon, 27 Jul 2026 15:07:39 +0000 (09:07 -0600)
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 <vjardin@free.fr>
Reviewed-by: Simon Glass <sjg@chromium.org>
fs/fs.c

diff --git a/fs/fs.c b/fs/fs.c
index 8ea50a6c13c403106ccc639c7c4e7fa2c4445a48..56f3e0c9204954fa730d58196441ba150c6c7cca 100644 (file)
--- 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)