From: Simon Glass <simon.glass@canonical.com>
Add a minimal ext4l probe function that:
- Reads the superblock from the block device
- Validates the ext4 magic number
- Returns proper error codes (-EINVAL, -ENOMEM, -EIO)
Create include/ext4l.h header with function declarations and
documentation. Update fs_legacy.c to use the header.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---
fs/ext4l/interface.c | 57 ++++++++++++++++++++++++++++++++++++++++++--
fs/fs_legacy.c | 5 ++--
include/ext4l.h | 31 ++++++++++++++++++++++++
3 files changed, 89 insertions(+), 4 deletions(-)
create mode 100644 include/ext4l.h
@@ -2,19 +2,72 @@
/*
* U-Boot interface for ext4l filesystem (Linux port)
*
+ * Copyright 2025 Canonical Ltd
+ * Written by Simon Glass <simon.glass@canonical.com>
+ *
* This provides the minimal interface between U-Boot and the ext4l driver.
- * Currently just stubs - the filesystem doesn't work yet.
*/
#include <blk.h>
#include <part.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#include "ext4_uboot.h"
+#include "ext4.h"
+
+/* Global state */
+static struct blk_desc *ext4l_dev_desc;
+static struct disk_partition ext4l_part;
int ext4l_probe(struct blk_desc *fs_dev_desc,
struct disk_partition *fs_partition)
{
- return -1;
+ loff_t part_offset;
+ __le16 *magic;
+ u8 *buf;
+ int ret;
+
+ if (!fs_dev_desc)
+ return -EINVAL;
+
+ buf = malloc(BLOCK_SIZE + 512);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Calculate partition offset in bytes */
+ part_offset = fs_partition ? (loff_t)fs_partition->start * fs_dev_desc->blksz : 0;
+
+ /* Read sectors containing the superblock */
+ if (blk_dread(fs_dev_desc,
+ (part_offset + BLOCK_SIZE) / fs_dev_desc->blksz,
+ 2, buf) != 2) {
+ ret = -EIO;
+ goto out;
+ }
+
+ /* Check magic number within superblock */
+ magic = (__le16 *)(buf + (BLOCK_SIZE % fs_dev_desc->blksz) +
+ offsetof(struct ext4_super_block, s_magic));
+ if (le16_to_cpu(*magic) != EXT4_SUPER_MAGIC) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Save device info for later operations */
+ ext4l_dev_desc = fs_dev_desc;
+ if (fs_partition)
+ memcpy(&ext4l_part, fs_partition, sizeof(ext4l_part));
+
+ ret = 0;
+out:
+ free(buf);
+ return ret;
}
void ext4l_close(void)
{
+ ext4l_dev_desc = NULL;
}
@@ -18,6 +18,7 @@
#include <mapmem.h>
#include <part.h>
#include <ext4fs.h>
+#include <ext4l.h>
#include <fat.h>
#include <fs_legacy.h>
#include <sandboxfs.h>
@@ -262,8 +263,8 @@ static struct fstype_info fstypes[] = {
.fstype = FS_TYPE_EXT,
.name = "ext4",
.null_dev_desc_ok = false,
- .probe = fs_probe_unsupported,
- .close = fs_close_unsupported,
+ .probe = ext4l_probe,
+ .close = ext4l_close,
.ls = fs_ls_unsupported,
.exists = fs_exists_unsupported,
.size = fs_size_unsupported,
new file mode 100644
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * ext4l filesystem interface
+ *
+ * Copyright 2025 Canonical Ltd
+ * Written by Simon Glass <simon.glass@canonical.com>
+ */
+
+#ifndef __EXT4L_H__
+#define __EXT4L_H__
+
+struct blk_desc;
+struct disk_partition;
+
+/**
+ * ext4l_probe() - Probe a block device for an ext4 filesystem
+ *
+ * @fs_dev_desc: Block device descriptor
+ * @fs_partition: Partition information
+ * Return: 0 on success, -EINVAL if no device or invalid magic,
+ * -ENOMEM on allocation failure, -EIO on read error
+ */
+int ext4l_probe(struct blk_desc *fs_dev_desc,
+ struct disk_partition *fs_partition);
+
+/**
+ * ext4l_close() - Close the ext4 filesystem
+ */
+void ext4l_close(void);
+
+#endif /* __EXT4L_H__ */