Browse Source

libfstools: add uImage.FIT fitblk driver

The upcoming 'fitblk' block driver exposing the filesystem sub-image(s)
of a uImage.FIT storage on a block device as /dev/fit%u.
In case of the block device being a fixed-sized partition, the remaining
space (for rootfs_data) is mapped to /dev/fitrw.
Recognize both devices and assign the highest priority to the new driver.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Daniel Golle 5 months ago
parent
commit
bc3b8cdd3d
4 changed files with 101 additions and 2 deletions
  1. 1 0
      CMakeLists.txt
  2. 2 0
      libfstools/common.h
  3. 98 0
      libfstools/fit.c
  4. 0 2
      libfstools/partname.c

+ 1 - 0
CMakeLists.txt

@@ -9,6 +9,7 @@ ADD_LIBRARY(fstools SHARED
 		libfstools/common.c
 		libfstools/snapshot.c
 		libfstools/extroot.c
+		libfstools/fit.c
 		libfstools/overlay.c
 		libfstools/volume.c
 		libfstools/mtd.c

+ 2 - 0
libfstools/common.h

@@ -25,3 +25,5 @@ int read_uint_from_file(char *dirname, char *filename, unsigned int *i);
 char *read_string_from_file(const char *dirname, const char *filename, char *buf, size_t bufsz);
 int block_file_identify(FILE *f, uint64_t offset);
 int block_volume_format(struct volume *v, uint64_t offset, const char *bdev);
+
+static const char *const block_dir_name = "/sys/class/block";

+ 98 - 0
libfstools/fit.c

@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common.h"
+
+#define BUFLEN 64
+
+static const char *const fit0 = "/dev/fit0";
+static const char *const fitrw = "/dev/fitrw";
+
+struct devpath {
+	char prefix[5];
+	char device[11];
+};
+
+struct fit_volume {
+	struct volume v;
+	union {
+		char devpathstr[16];
+		struct devpath devpath;
+	} dev;
+};
+
+static struct driver fit_driver;
+
+static int fit_volume_identify(struct volume *v)
+{
+	struct fit_volume *p = container_of(v, struct fit_volume, v);
+	int ret = FS_NONE;
+	FILE *f;
+
+	f = fopen(p->dev.devpathstr, "r");
+	if (!f)
+		return ret;
+
+	ret = block_file_identify(f, 0);
+
+	fclose(f);
+
+	return ret;
+}
+
+static int fit_volume_init(struct volume *v)
+{
+	struct fit_volume *p = container_of(v, struct fit_volume, v);
+	char voldir[BUFLEN];
+	unsigned int volsize;
+
+	snprintf(voldir, sizeof(voldir), "%s/%s", block_dir_name, p->dev.devpath.device);
+
+	if (read_uint_from_file(voldir, "size", &volsize))
+		return -1;
+
+	v->type = BLOCKDEV;
+	v->size = volsize << 9; /* size is returned in sectors of 512 bytes */
+	v->blk = p->dev.devpathstr;
+
+	return block_volume_format(v, 0, p->dev.devpathstr);
+}
+
+static struct volume *fit_volume_find(char *name)
+{
+	struct fit_volume *p;
+	struct stat buf;
+	const char *fname;
+	int ret;
+
+	if (!strcmp(name, "rootfs"))
+		fname = fit0;
+	else if (!strcmp(name, "rootfs_data"))
+		fname = fitrw;
+	else
+		return NULL;
+
+	ret = stat(fname, &buf);
+	if (ret)
+		return NULL;
+
+	p = calloc(1, sizeof(struct fit_volume));
+	if (!p)
+		return NULL;
+
+	strcpy(p->dev.devpathstr, fname);
+	p->v.drv = &fit_driver;
+	p->v.blk = p->dev.devpathstr;
+	p->v.name = name;
+
+	return &p->v;
+}
+
+static struct driver fit_driver = {
+	.name = "fit",
+	.priority = 30,
+	.find = fit_volume_find,
+	.init = fit_volume_init,
+	.identify = fit_volume_identify,
+};
+
+DRIVER(fit_driver);

+ 0 - 2
libfstools/partname.c

@@ -4,8 +4,6 @@
 
 #define BUFLEN 64
 
-const char *const block_dir_name = "/sys/class/block";
-
 struct devpath {
 	char prefix[5];
 	char device[11];