summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Jardin <[email protected]>2026-07-15 18:57:15 +0200
committerTom Rini <[email protected]>2026-07-27 09:07:39 -0600
commit5b1dac9ee2029c6aa9fe4f8554f2250b94b89da2 (patch)
treeb8f02eb9cc1fa254065418987d3acf6aceacdf50
parentf605dcee103c897b6f1a8873549a36949bd4e2a1 (diff)
fs: dispatch null_dev_desc_ok filesystems before lookup
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]> Reviewed-by: Simon Glass <[email protected]>
-rw-r--r--fs/fs.c42
1 files changed, 42 insertions, 0 deletions
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)