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
, *voltype
;
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
)))
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 ubi_dir
= opendir(ubi_dir_name
);
184 /* check for os ubi support */
188 /* probe ubi devices and volumes */
189 while ((ubi_dirent
= readdir(ubi_dir
)) != NULL
) {
190 if (ubi_dirent
->d_name
[0] == '.')
193 sscanf(ubi_dirent
->d_name
, "ubi%u", &ubi_num
);
194 if (!ubi_part_match(v
, name
, ubi_num
)) {
203 static int ubi_volume_identify(struct volume
*v
)
208 static struct driver ubi_driver
= {
210 .find
= ubi_volume_find
,
211 .init
= ubi_volume_init
,
212 .identify
= ubi_volume_identify
,