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.
16 /* fit for UBI_MAX_VOLUME_NAME and sysfs path lengths */
19 /* could use libubi-tiny instead, but already had the code directly reading
21 const char *const ubi_dir_name
= "/sys/class/ubi";
29 static struct driver ubi_driver
;
32 test_open(char *filename
)
36 f
= fopen(filename
, "r");
44 static int ubi_volume_init(struct volume
*v
)
46 struct ubi_volume
*p
= container_of(v
, struct ubi_volume
, v
);
47 char voldir
[BUFLEN
], voldev
[BUFLEN
], volname
[BUFLEN
];
50 snprintf(voldir
, sizeof(voldir
), "%s/ubi%u_%u",
51 ubi_dir_name
, p
->ubi_num
, p
->ubi_volid
);
53 snprintf(voldev
, sizeof(voldev
), "/dev/ubi%u_%u",
54 p
->ubi_num
, p
->ubi_volid
);
56 if (!read_string_from_file(voldir
, "name", volname
, sizeof(volname
)))
59 if (read_uint_from_file(voldir
, "data_bytes", &volsize
))
65 v
->blk
= strdup(voldev
);
70 static struct volume
*ubi_volume_match(char *name
, int ubi_num
, int volid
)
72 char voldir
[BUFLEN
], volblkdev
[BUFLEN
], volname
[BUFLEN
];
75 snprintf(voldir
, sizeof(voldir
), "%s/ubi%u_%u",
76 ubi_dir_name
, ubi_num
, volid
);
78 snprintf(volblkdev
, sizeof(volblkdev
), "/dev/ubiblock%u_%u",
81 /* skip if ubiblock device exists */
82 if (test_open(volblkdev
))
85 /* todo: skip existing gluebi device for legacy support */
87 if (!read_string_from_file(voldir
, "name", volname
, sizeof(volname
))) {
88 ULOG_ERR("Couldn't read %s/name\n", voldir
);
92 if (strcmp(name
, volname
))
95 p
= calloc(1, sizeof(struct ubi_volume
));
99 p
->v
.drv
= &ubi_driver
;
100 p
->ubi_num
= ubi_num
;
101 p
->ubi_volid
= volid
;
106 static struct volume
*ubi_part_match(char *name
, unsigned int ubi_num
)
109 struct dirent
*ubi_dirent
;
112 struct volume
*ret
= NULL
;
114 snprintf(devdir
, sizeof(devdir
), "%s/ubi%u",
115 ubi_dir_name
, ubi_num
);
117 ubi_dir
= opendir(devdir
);
121 while ((ubi_dirent
= readdir(ubi_dir
)) != NULL
) {
122 if (strncmp(ubi_dirent
->d_name
, "ubi", 3))
125 if (sscanf(ubi_dirent
->d_name
, "ubi%*u_%u", &volid
) != 1)
128 ret
= ubi_volume_match(name
, ubi_num
, volid
);
137 static struct volume
*ubi_volume_find(char *name
)
139 struct volume
*ret
= NULL
;
141 struct dirent
*ubi_dirent
;
142 unsigned int ubi_num
;
144 if (find_filesystem("ubifs"))
147 ubi_dir
= opendir(ubi_dir_name
);
148 /* check for os ubi support */
152 /* probe ubi devices and volumes */
153 while ((ubi_dirent
= readdir(ubi_dir
)) != NULL
) {
154 if (ubi_dirent
->d_name
[0] == '.')
157 sscanf(ubi_dirent
->d_name
, "ubi%u", &ubi_num
);
158 ret
= ubi_part_match(name
, ubi_num
);
166 static int ubi_volume_identify(struct volume
*v
)
168 /* Todo: use libblkid-tiny on the ubi chardev */
172 static struct driver ubi_driver
= {
175 .find
= ubi_volume_find
,
176 .init
= ubi_volume_init
,
177 .identify
= ubi_volume_identify
,