2 * Copyright (C) 2014 John Crispin <blogic@openwrt.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.
14 #include <sys/types.h>
24 #include "libubi/libubi-tiny.h"
26 static int print_usage(void)
29 printf("ubi detach kernel|rootfs\n");
30 printf("ubi kernel <image.kernel.ubi>\n");
31 printf("ubi rootfs <image.rootfs.ubi>\n");
32 printf("ubi overlay <image.rootfs-overlay.ubi>\n");
37 static int mtd_find_index(char *name)
39 FILE *fp = fopen("/proc/mtd", "r");
46 while (!index && fgets(line, sizeof(line), fp)) {
47 if (strstr(line, name)) {
48 char *eol = strstr(line, ":");
66 static int mtd_find(char *name, char *ret)
68 int index = mtd_find_index(name);
72 sprintf(ret, "/dev/mtd%d", index);
77 static int ubi_find(libubi_t libubi, char *name, char *ret)
79 int index = mtd_find_index(name);
82 while (ubi_dev_present(libubi, ubi))
84 struct ubi_dev_info info;
86 if (ubi_get_dev_info1(libubi, ubi++, &info))
89 if (info.mtd_num != index)
92 sprintf(ret, "/dev/ubi%d", info.dev_num);
100 static int volume_find(libubi_t libubi, char *name, char *ret)
102 int index = mtd_find_index(name);
103 struct ubi_vol_info vol;
109 if (mtd_num2ubi_dev(libubi, index, &ubi)) {
110 fprintf(stderr, "failed to get ubi node for %s\n", name);
114 if (ubi_get_vol_info1_nm(libubi, ubi, name, &vol)) {
115 fprintf(stderr, "failed to get ubi volume info for %s\n", name);
119 sprintf(ret, "/dev/ubi%d_%d", ubi, vol.vol_id);
124 static int main_detach(char *type)
130 if (!strcmp(type, "kernel"))
131 err = mtd_find("kernel_ubi", mtd);
132 else if (!strcmp(type, "rootfs"))
133 err = mtd_find("rootfs_ubi", mtd);
135 return print_usage();
138 fprintf(stderr, "failed to find mtd partition %s_ubi\n", type);
142 libubi = libubi_open();
144 fprintf(stderr, "cannot open libubi");
148 err = ubidetach(libubi, mtd);
150 fprintf(stderr, "cannot detach \"%s\"", mtd);
157 static int main_image(char *partition, char *image, char *overlay)
169 if (stat(image, &s)) {
170 fprintf(stderr, "image not found %s\n", image);
174 if (!strcmp(partition, "kernel"))
175 err = mtd_find("kernel", _part);
177 err = mtd_find("rootfs", _part);
179 if (overlay && !mtd_find(overlay, _data))
182 libubi = libubi_open();
184 fprintf(stderr, "cannot open libubi");
188 if (!strcmp(partition, "kernel"))
189 err = mtd_find("kernel_ubi", mtd);
191 err = mtd_find("rootfs_ubi", mtd);
193 fprintf(stderr, "failed to find mtd parent %s_ubi\n", partition);
197 if (!strcmp(partition, "kernel"))
198 err = ubi_find(libubi, "kernel_ubi", node);
200 err = ubi_find(libubi, "rootfs_ubi", node);
202 fprintf(stderr, "failed to find ubi volume %s\n", partition);
206 err = ubidetach(libubi, mtd);
208 fprintf(stderr, "cannot detach \"%s\"", mtd);
212 err = ubiattach(libubi, mtd);
214 fprintf(stderr, "cannot attach \"%s\"", mtd);
219 err = ubirmvol(libubi, node, overlay);
221 fprintf(stderr, "cannot remove \"%s\"", node);
226 if (volume_find(libubi, partition, volume) < 0) {
227 fprintf(stderr, "failed to find ubi volume %s\n", partition);
231 err = ubirsvol(libubi, node, partition, s.st_size);
233 fprintf(stderr, "cannot resize \"%s\"", partition);
237 err = ubiupdatevol(libubi, volume, image);
239 fprintf(stderr, "cannot update \"%s\"", volume);
244 err = ubimkvol(libubi, node, overlay, 1);
246 fprintf(stderr, "cannot make \"%s\"", overlay);
251 libubi_close(libubi);
256 static int main_info(void)
258 struct ubi_info info;
262 libubi = libubi_open();
264 fprintf(stderr, "cannot open libubi");
268 if (ubi_get_info(libubi, &info)) {
269 fprintf(stderr, "failed to get info\n");
273 for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
274 struct ubi_dev_info dinfo;
278 sprintf(ubi, "/dev/ubi%d", i);
279 if (ubi_get_dev_info(libubi, ubi, &dinfo))
281 printf("device - %s\n size: %lldBytes\n bad blocks: %d\n",
282 &ubi[5], dinfo.total_bytes, dinfo.bad_count);
283 for (j = dinfo.lowest_vol_id; j <= dinfo.highest_vol_id; j++) {
284 struct ubi_vol_info vinfo;
286 sprintf(ubi, "/dev/ubi%d_%d", i, j);
287 if (ubi_get_vol_info(libubi, ubi, &vinfo))
289 printf(" volume - %s\n", &ubi[5]);
290 printf("\tname: %s\n", vinfo.name);
291 printf("\tsize: %lld\n", vinfo.data_bytes);
295 libubi_close(libubi);
300 int main(int argc, char **argv)
302 if (argc > 1 && !strcmp(argv[1], "info"))
306 return print_usage();
308 if (!strcmp(argv[1], "kernel")) {
309 return main_image("kernel", argv[2], NULL);
311 } else if (!strcmp(argv[1], "rootfs")) {
312 return main_image("rootfs", argv[2], NULL);
314 } else if (!strcmp(argv[1], "overlay")) {
315 return main_image("rootfs", argv[2], "rootfs_data");
317 } else if (!strcmp(argv[1], "detach")) {
318 return main_detach(argv[2]);