2 * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
19 #include "libfstools.h"
22 /* could use libubi-tiny instead, but already had the code directly reading
24 char *ubi_dir_name = "/sys/devices/virtual/ubi";
31 static struct driver ubi_driver;
34 read_uint_from_file(char *dirname, char *filename, unsigned int *i)
40 snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
42 f = fopen(fname, "r");
46 if (fscanf(f, "%u", i) == 1)
54 *read_string_from_file(char *dirname, char *filename)
62 snprintf(fname, sizeof(fname), "%s/%s", dirname, filename);
64 f = fopen(fname, "r");
68 if (fgets(buf, 128, f) == NULL)
74 while (buf[i] == '\n');
82 test_open(char *filename)
86 f = fopen(filename, "r");
94 static int ubi_volume_init(struct volume *v)
96 char voldir[40], voldev[32], *volname;
100 p = (struct ubi_priv*)v->priv;
102 snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
103 ubi_dir_name, p->ubi_num, p->ubi_num, p->ubi_volidx);
105 snprintf(voldev, sizeof(voldev), "/dev/ubi%u_%u",
106 p->ubi_num, p->ubi_volidx);
108 volname = read_string_from_file(voldir, "name");
112 if (read_uint_from_file(voldir, "data_bytes", &volsize))
118 v->blk = strdup(voldev);
124 static int ubi_volume_match(struct volume *v, char *name, int ubi_num, int volidx)
126 char voldir[40], volblkdev[40], *volname;
129 snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
130 ubi_dir_name, ubi_num, ubi_num, volidx);
132 snprintf(volblkdev, sizeof(volblkdev), "/dev/ubiblock%u_%u",
135 /* skip if ubiblock device exists */
136 if (test_open(volblkdev))
139 volname = read_string_from_file(voldir, "name");
141 if (strncmp(name, volname, strlen(volname) + 1))
144 p = calloc(1, sizeof(struct ubi_priv));
149 v->drv = &ubi_driver;
150 p->ubi_num = ubi_num;
151 p->ubi_volidx = volidx;
153 return ubi_volume_init(v);
156 static int ubi_part_match(struct volume *v, char *name, unsigned int ubi_num)
158 unsigned int i, volumes_count;
161 snprintf(devdir, sizeof(devdir), "%s/ubi%u",
162 ubi_dir_name, ubi_num);
164 if (read_uint_from_file(devdir, "volumes_count", &volumes_count))
167 for (i=0;i<volumes_count;i++) {
168 if (!ubi_volume_match(v, name, ubi_num, i)) {
176 static int ubi_volume_find(struct volume *v, char *name)
179 struct dirent *ubi_dirent;
180 unsigned int ubi_num;
183 if (find_filesystem("ubifs"))
186 ubi_dir = opendir(ubi_dir_name);
187 /* check for os ubi support */
191 /* probe ubi devices and volumes */
192 while ((ubi_dirent = readdir(ubi_dir)) != NULL) {
193 if (ubi_dirent->d_name[0] == '.')
196 sscanf(ubi_dirent->d_name, "ubi%u", &ubi_num);
197 if (!ubi_part_match(v, name, ubi_num)) {
206 static int ubi_volume_identify(struct volume *v)
211 static struct driver ubi_driver = {
213 .find = ubi_volume_find,
214 .init = ubi_volume_init,
215 .identify = ubi_volume_identify,