ubimkvol.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright (c) International Business Machines Corp., 2006
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  12. * the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. /*
  19. * An utility to create UBI volumes.
  20. *
  21. * Authors: Artem Bityutskiy <dedekind@infradead.org>
  22. * Frank Haverkamp <haver@vnet.ibm.com>
  23. */
  24. #define PROGRAM_NAME "ubimkvol"
  25. #include <stdio.h>
  26. #include <stdint.h>
  27. #include <getopt.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <libubi.h>
  31. #include "common.h"
  32. /* The variables below are set by command line arguments */
  33. struct args {
  34. int vol_id;
  35. int vol_type;
  36. long long bytes;
  37. int lebs;
  38. int alignment;
  39. const char *name;
  40. const char *node;
  41. int maxavs;
  42. int skipcheck;
  43. };
  44. static struct args args = {
  45. .vol_type = UBI_DYNAMIC_VOLUME,
  46. .bytes = -1,
  47. .lebs = -1,
  48. .alignment = 1,
  49. .vol_id = UBI_VOL_NUM_AUTO,
  50. };
  51. static const char doc[] = PROGRAM_NAME " version " VERSION
  52. " - a tool to create UBI volumes.";
  53. static const char optionsstr[] =
  54. "-a, --alignment=<alignment> volume alignment (default is 1)\n"
  55. "-n, --vol_id=<volume ID> UBI volume ID, if not specified, the volume ID\n"
  56. " will be assigned automatically\n"
  57. "-N, --name=<name> volume name\n"
  58. "-s, --size=<bytes> volume size volume size in bytes, kilobytes (KiB)\n"
  59. " or megabytes (MiB)\n"
  60. "-S, --lebs=<LEBs count> alternative way to give volume size in logical\n"
  61. " eraseblocks\n"
  62. "-m, --maxavsize set volume size to maximum available size\n"
  63. "-t, --type=<static|dynamic> volume type (dynamic, static), default is dynamic\n"
  64. "-k, --skipcheck skip the CRC check done at volume open time\n"
  65. "-h, -?, --help print help message\n"
  66. "-V, --version print program version";
  67. static const char usage[] =
  68. "Usage: " PROGRAM_NAME " <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]\n"
  69. "\t\t\t[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m] [-k]\n"
  70. "\t\t\t[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]\n"
  71. "\t\t\t[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]\n"
  72. "\t\t\t[--version] [--maxavsize] [--skipcheck]\n\n"
  73. "Example: " PROGRAM_NAME " /dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n"
  74. " named \"config_data\" on UBI device /dev/ubi0.";
  75. static const struct option long_options[] = {
  76. { .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' },
  77. { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
  78. { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' },
  79. { .name = "size", .has_arg = 1, .flag = NULL, .val = 's' },
  80. { .name = "lebs", .has_arg = 1, .flag = NULL, .val = 'S' },
  81. { .name = "type", .has_arg = 1, .flag = NULL, .val = 't' },
  82. { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
  83. { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
  84. { .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' },
  85. { .name = "skipcheck", .has_arg = 0, .flag = NULL, .val = 'k' },
  86. { NULL, 0, NULL, 0},
  87. };
  88. static int param_sanity_check(void)
  89. {
  90. int len;
  91. if (args.bytes == -1 && !args.maxavs && args.lebs == -1)
  92. return errmsg("volume size was not specified (use -h for help)");
  93. if ((args.bytes != -1 && (args.maxavs || args.lebs != -1)) ||
  94. (args.lebs != -1 && (args.maxavs || args.bytes != -1)) ||
  95. (args.maxavs && (args.bytes != -1 || args.lebs != -1)))
  96. return errmsg("size specified with more then one option");
  97. if (args.name == NULL)
  98. return errmsg("volume name was not specified (use -h for help)");
  99. len = strlen(args.name);
  100. if (len > UBI_MAX_VOLUME_NAME)
  101. return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME);
  102. if (args.skipcheck && args.vol_type != UBI_STATIC_VOLUME)
  103. return errmsg("skipcheck is only valid for static volumes");
  104. return 0;
  105. }
  106. static int parse_opt(int argc, char * const argv[])
  107. {
  108. while (1) {
  109. int key, error = 0;
  110. key = getopt_long(argc, argv, "a:n:N:s:S:t:h?Vmk", long_options, NULL);
  111. if (key == -1)
  112. break;
  113. switch (key) {
  114. case 't':
  115. if (!strcmp(optarg, "dynamic"))
  116. args.vol_type = UBI_DYNAMIC_VOLUME;
  117. else if (!strcmp(optarg, "static"))
  118. args.vol_type = UBI_STATIC_VOLUME;
  119. else
  120. return errmsg("bad volume type: \"%s\"", optarg);
  121. break;
  122. case 's':
  123. args.bytes = util_get_bytes(optarg);
  124. if (args.bytes <= 0)
  125. return errmsg("bad volume size: \"%s\"", optarg);
  126. break;
  127. case 'S':
  128. args.lebs = simple_strtoull(optarg, &error);
  129. if (error || args.lebs <= 0)
  130. return errmsg("bad LEB count: \"%s\"", optarg);
  131. break;
  132. case 'a':
  133. args.alignment = simple_strtoul(optarg, &error);
  134. if (error || args.alignment <= 0)
  135. return errmsg("bad volume alignment: \"%s\"", optarg);
  136. break;
  137. case 'n':
  138. args.vol_id = simple_strtoul(optarg, &error);
  139. if (error || args.vol_id < 0)
  140. return errmsg("bad volume ID: " "\"%s\"", optarg);
  141. break;
  142. case 'N':
  143. args.name = optarg;
  144. break;
  145. case 'h':
  146. printf("%s\n\n", doc);
  147. printf("%s\n\n", usage);
  148. printf("%s\n", optionsstr);
  149. exit(EXIT_SUCCESS);
  150. case '?':
  151. printf("%s\n\n", doc);
  152. printf("%s\n\n", usage);
  153. printf("%s\n", optionsstr);
  154. return -1;
  155. case 'V':
  156. common_print_version();
  157. exit(EXIT_SUCCESS);
  158. case 'm':
  159. args.maxavs = 1;
  160. break;
  161. case 'k':
  162. args.skipcheck = 1;
  163. break;
  164. case ':':
  165. return errmsg("parameter is missing");
  166. default:
  167. fprintf(stderr, "Use -h for help\n");
  168. return -1;
  169. }
  170. }
  171. if (optind == argc)
  172. return errmsg("UBI device name was not specified (use -h for help)");
  173. else if (optind != argc - 1)
  174. return errmsg("more then one UBI device specified (use -h for help)");
  175. args.node = argv[optind];
  176. if (param_sanity_check())
  177. return -1;
  178. return 0;
  179. }
  180. int main(int argc, char * const argv[])
  181. {
  182. int err;
  183. libubi_t libubi;
  184. struct ubi_dev_info dev_info;
  185. struct ubi_vol_info vol_info;
  186. struct ubi_mkvol_request req = { };
  187. err = parse_opt(argc, argv);
  188. if (err)
  189. return err;
  190. libubi = libubi_open();
  191. if (!libubi) {
  192. if (errno == 0)
  193. return errmsg("UBI is not present in the system");
  194. return sys_errmsg("cannot open libubi");
  195. }
  196. err = ubi_probe_node(libubi, args.node);
  197. if (err == 2) {
  198. errmsg("\"%s\" is an UBI volume node, not an UBI device node",
  199. args.node);
  200. goto out_libubi;
  201. } else if (err < 0) {
  202. if (errno == ENODEV)
  203. errmsg("\"%s\" is not an UBI device node", args.node);
  204. else
  205. sys_errmsg("error while probing \"%s\"", args.node);
  206. goto out_libubi;
  207. }
  208. err = ubi_get_dev_info(libubi, args.node, &dev_info);
  209. if (err) {
  210. sys_errmsg("cannot get information about UBI device \"%s\"",
  211. args.node);
  212. goto out_libubi;
  213. }
  214. if (dev_info.avail_bytes == 0) {
  215. errmsg("UBI device does not have free logical eraseblocks");
  216. goto out_libubi;
  217. }
  218. if (args.maxavs) {
  219. args.bytes = dev_info.avail_bytes;
  220. printf("Set volume size to %lld\n", args.bytes);
  221. }
  222. if (args.lebs != -1) {
  223. args.bytes = dev_info.leb_size;
  224. args.bytes -= dev_info.leb_size % args.alignment;
  225. args.bytes *= args.lebs;
  226. }
  227. req.vol_id = args.vol_id;
  228. req.alignment = args.alignment;
  229. req.bytes = args.bytes;
  230. req.vol_type = args.vol_type;
  231. req.name = args.name;
  232. if (args.skipcheck)
  233. req.flags |= UBI_VOL_SKIP_CRC_CHECK_FLG;
  234. err = ubi_mkvol(libubi, args.node, &req);
  235. if (err < 0) {
  236. sys_errmsg("cannot UBI create volume");
  237. goto out_libubi;
  238. }
  239. args.vol_id = req.vol_id;
  240. /* Print information about the created device */
  241. err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info);
  242. if (err) {
  243. sys_errmsg("cannot get information about newly created UBI volume");
  244. goto out_libubi;
  245. }
  246. printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
  247. util_print_bytes(vol_info.rsvd_bytes, 0);
  248. printf("), LEB size ");
  249. util_print_bytes(vol_info.leb_size, 1);
  250. printf(", %s, name \"%s\", alignment %d\n",
  251. req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
  252. vol_info.name, vol_info.alignment);
  253. libubi_close(libubi);
  254. return 0;
  255. out_libubi:
  256. libubi_close(libubi);
  257. return -1;
  258. }