libubi-tiny.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright (C) 2007 Nokia Corporation.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License version 2 as published by
  6. * the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along with
  14. * this program; if not, write to the Free Software Foundation, Inc., 51
  15. * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. /*
  18. * An utility to delete UBI devices (detach MTD devices from UBI).
  19. *
  20. * Author: Artem Bityutskiy
  21. */
  22. #define PROGRAM_NAME "ubidetach"
  23. #define VERSION "owrt-fstools"
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <fcntl.h>
  27. #include <stdio.h>
  28. #include <stdint.h>
  29. #include <getopt.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include "libubi-tiny.h"
  34. #define DEFAULT_CTRL_DEV "/dev/ubi_ctrl"
  35. static int ubi_write(char *node, int fd, const void *buf, int len)
  36. {
  37. int ret;
  38. while (len) {
  39. ret = write(fd, buf, len);
  40. if (ret < 0) {
  41. if (errno == EINTR) {
  42. fprintf(stderr, "do not interrupt me!");
  43. continue;
  44. }
  45. fprintf(stderr, "cannot write %d bytes to volume \"%s\"", len, node);
  46. return -1;
  47. }
  48. if (ret == 0) {
  49. fprintf(stderr, "cannot write %d bytes to volume \"%s\"", len, node);
  50. return -1;
  51. }
  52. len -= ret;
  53. buf += ret;
  54. }
  55. return 0;
  56. }
  57. static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info, char *node, char *img, int skip)
  58. {
  59. int err, fd, ifd;
  60. long long bytes;
  61. char *buf;
  62. struct stat st;
  63. buf = malloc(vol_info->leb_size);
  64. if (!buf) {
  65. fprintf(stderr, "cannot allocate %d bytes of memory", vol_info->leb_size);
  66. return -1;
  67. }
  68. err = stat(img, &st);
  69. if (err < 0) {
  70. fprintf(stderr, "stat failed on \"%s\"", img);
  71. goto out_free;
  72. }
  73. bytes = st.st_size - skip;
  74. if (bytes > vol_info->rsvd_bytes) {
  75. fprintf(stderr, "\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
  76. img, bytes, node, vol_info->rsvd_bytes);
  77. goto out_free;
  78. }
  79. fd = open(node, O_RDWR);
  80. if (fd == -1) {
  81. fprintf(stderr, "cannot open UBI volume \"%s\"", node);
  82. goto out_free;
  83. }
  84. ifd = open(img, O_RDONLY);
  85. if (ifd == -1) {
  86. fprintf(stderr, "cannot open \"%s\"", img);
  87. goto out_close1;
  88. }
  89. if (skip && lseek(ifd, skip, SEEK_CUR) == -1) {
  90. fprintf(stderr, "lseek input by %d failed", skip);
  91. goto out_close;
  92. }
  93. err = ubi_update_start(libubi, fd, bytes);
  94. if (err) {
  95. fprintf(stderr, "cannot start volume \"%s\" update", node);
  96. goto out_close;
  97. }
  98. while (bytes) {
  99. ssize_t ret;
  100. int to_copy = vol_info->leb_size;
  101. if (to_copy > bytes)
  102. to_copy = bytes;
  103. ret = read(ifd, buf, to_copy);
  104. if (ret <= 0) {
  105. if (errno == EINTR) {
  106. fprintf(stderr, "do not interrupt me!");
  107. continue;
  108. } else {
  109. fprintf(stderr, "cannot read %d bytes from \"%s\"",
  110. to_copy, img);
  111. goto out_close;
  112. }
  113. }
  114. err = ubi_write(node, fd, buf, ret);
  115. if (err)
  116. goto out_close;
  117. bytes -= ret;
  118. }
  119. close(ifd);
  120. close(fd);
  121. free(buf);
  122. return 0;
  123. out_close:
  124. close(ifd);
  125. out_close1:
  126. close(fd);
  127. out_free:
  128. free(buf);
  129. return -1;
  130. }
  131. int ubiattach(libubi_t libubi, char *mtd)
  132. {
  133. struct ubi_attach_request req = {
  134. .dev_num = UBI_DEV_NUM_AUTO,
  135. .mtd_num = -1,
  136. .vid_hdr_offset = 0,
  137. .max_beb_per1024 = 0,
  138. .mtd_dev_node = mtd,
  139. };
  140. int err = ubi_attach(libubi, DEFAULT_CTRL_DEV, &req);
  141. if (err) {
  142. fprintf(stderr, "cannot attach \"%s\"", mtd);
  143. return err;
  144. }
  145. return 0;
  146. }
  147. int ubidetach(libubi_t libubi, char *mtd)
  148. {
  149. return ubi_detach(libubi, DEFAULT_CTRL_DEV, mtd);
  150. }
  151. int ubirsvol(libubi_t libubi, char *node, char *name, int bytes)
  152. {
  153. struct ubi_dev_info dev_info;
  154. struct ubi_vol_info vol_info;
  155. int err = ubi_get_dev_info(libubi, node, &dev_info);
  156. if (err) {
  157. fprintf(stderr, "cannot get information about UBI device \"%s\"",
  158. node);
  159. return -1;
  160. }
  161. err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, name, &vol_info);
  162. if (err) {
  163. fprintf(stderr, "cannot find UBI volume \"%s\"", name);
  164. return -1;
  165. }
  166. err = ubi_rsvol(libubi, node, vol_info.vol_id, bytes);
  167. if (err) {
  168. fprintf(stderr, "cannot UBI resize volume");
  169. return -1;
  170. }
  171. return 0;
  172. }
  173. int ubirmvol(libubi_t libubi, char *node, char *name)
  174. {
  175. struct ubi_dev_info dev_info;
  176. struct ubi_vol_info vol_info;
  177. int err = ubi_get_dev_info(libubi, node, &dev_info);
  178. if (err) {
  179. fprintf(stderr, "cannot get information about UBI device \"%s\"",
  180. node);
  181. return -1;
  182. }
  183. err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num, name, &vol_info);
  184. if (err) {
  185. fprintf(stderr, "cannot find UBI volume \"%s\"", name);
  186. return -1;
  187. }
  188. err = ubi_rmvol(libubi, node, vol_info.vol_id);
  189. if (err) {
  190. fprintf(stderr, "cannot UBI remove volume");
  191. return -1;
  192. }
  193. return 0;
  194. }
  195. int ubimkvol(libubi_t libubi, char *node, char *name, int maxavs)
  196. {
  197. struct ubi_dev_info dev_info;
  198. struct ubi_vol_info vol_info;
  199. struct ubi_mkvol_request req;
  200. int err = ubi_get_dev_info(libubi, node, &dev_info);
  201. if (err) {
  202. fprintf(stderr, "cannot get information about UBI device \"%s\"",
  203. node);
  204. return -1;
  205. }
  206. if (dev_info.avail_bytes == 0) {
  207. fprintf(stderr, "UBI device does not have free logical eraseblocks");
  208. return -1;
  209. }
  210. if (maxavs)
  211. printf("Set volume size to %lld\n", dev_info.avail_bytes);
  212. req.vol_id = UBI_VOL_NUM_AUTO;
  213. req.alignment = 1;
  214. req.bytes = dev_info.avail_bytes;
  215. req.vol_type = UBI_DYNAMIC_VOLUME;
  216. req.name = name;
  217. err = ubi_mkvol(libubi, node, &req);
  218. if (err < 0) {
  219. fprintf(stderr, "cannot UBI create volume");
  220. return -1;
  221. }
  222. /* Print information about the created device */
  223. err = ubi_get_vol_info1(libubi, dev_info.dev_num, req.vol_id, &vol_info);
  224. if (err) {
  225. fprintf(stderr, "cannot get information about newly created UBI volume");
  226. return -1;
  227. }
  228. printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
  229. ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
  230. printf("), LEB size ");
  231. ubiutils_print_bytes(vol_info.leb_size, 1);
  232. printf(", %s, name \"%s\", alignment %d\n",
  233. req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
  234. vol_info.name, vol_info.alignment);
  235. return 0;
  236. }
  237. int ubiupdatevol(libubi_t libubi, char *node, char *file)
  238. {
  239. struct ubi_vol_info vol_info;
  240. int err = ubi_get_vol_info(libubi, node, &vol_info);
  241. if (err) {
  242. fprintf(stderr, "cannot get information about UBI volume \"%s\"",
  243. node);
  244. return -1;
  245. }
  246. return update_volume(libubi, &vol_info, node, file, 0);
  247. }
  248. int ubitruncatevol(libubi_t libubi, char *node)
  249. {
  250. int err, fd;
  251. fd = open(node, O_RDWR);
  252. if (fd == -1) {
  253. fprintf(stderr, "cannot open \"%s\"", node);
  254. return -1;
  255. }
  256. err = ubi_update_start(libubi, fd, 0);
  257. if (err) {
  258. fprintf(stderr, "cannot truncate volume \"%s\"", node);
  259. close(fd);
  260. return -1;
  261. }
  262. close(fd);
  263. return 0;
  264. }