ubinize.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. /*
  2. * Copyright (C) 2008 Nokia Corporation
  3. * Copyright (c) International Business Machines Corp., 2006
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  13. * the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. /*
  20. * Generate UBI images.
  21. *
  22. * Authors: Artem Bityutskiy
  23. * Oliver Lohmann
  24. */
  25. #define PROGRAM_NAME "ubinize"
  26. #include <sys/stat.h>
  27. #include <stdlib.h>
  28. #include <getopt.h>
  29. #include <string.h>
  30. #include <fcntl.h>
  31. #include <mtd/ubi-media.h>
  32. #include <libubigen.h>
  33. #include <libiniparser.h>
  34. #include <libubi.h>
  35. #include "common.h"
  36. static const char optionsstr[] =
  37. "-o, --output=<file name> output file name\n"
  38. "-p, --peb-size=<bytes> size of the physical eraseblock of the flash\n"
  39. " this UBI image is created for in bytes,\n"
  40. " kilobytes (KiB), or megabytes (MiB)\n"
  41. " (mandatory parameter)\n"
  42. "-m, --min-io-size=<bytes> minimum input/output unit size of the flash\n"
  43. " in bytes\n"
  44. "-s, --sub-page-size=<bytes> minimum input/output unit used for UBI\n"
  45. " headers, e.g. sub-page size in case of NAND\n"
  46. " flash (equivalent to the minimum input/output\n"
  47. " unit size by default)\n"
  48. "-O, --vid-hdr-offset=<num> offset if the VID header from start of the\n"
  49. " physical eraseblock (default is the next\n"
  50. " minimum I/O unit or sub-page after the EC\n"
  51. " header)\n"
  52. "-e, --erase-counter=<num> the erase counter value to put to EC headers\n"
  53. " (default is 0)\n"
  54. "-x, --ubi-ver=<num> UBI version number to put to EC headers\n"
  55. " (default is 1)\n"
  56. "-Q, --image-seq=<num> 32-bit UBI image sequence number to use\n"
  57. " (by default a random number is picked)\n"
  58. "-v, --verbose be verbose\n"
  59. "-h, --help print help message\n"
  60. "-V, --version print program version\n\n";
  61. static const char usage[] =
  62. "Usage: " PROGRAM_NAME " [options] <ini-file>\n\n"
  63. "Generate UBI images. An UBI image may contain one or more UBI volumes which\n"
  64. "have to be defined in the input configuration ini-file. The flash\n"
  65. "characteristics are defined via the command-line options.\n\n";
  66. static const struct option long_options[] = {
  67. { .name = "output", .has_arg = 1, .flag = NULL, .val = 'o' },
  68. { .name = "peb-size", .has_arg = 1, .flag = NULL, .val = 'p' },
  69. { .name = "min-io-size", .has_arg = 1, .flag = NULL, .val = 'm' },
  70. { .name = "sub-page-size", .has_arg = 1, .flag = NULL, .val = 's' },
  71. { .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
  72. { .name = "erase-counter", .has_arg = 1, .flag = NULL, .val = 'e' },
  73. { .name = "ubi-ver", .has_arg = 1, .flag = NULL, .val = 'x' },
  74. { .name = "image-seq", .has_arg = 1, .flag = NULL, .val = 'Q' },
  75. { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
  76. { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
  77. { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
  78. { NULL, 0, NULL, 0}
  79. };
  80. struct args {
  81. const char *f_in;
  82. const char *f_out;
  83. int out_fd;
  84. int peb_size;
  85. int min_io_size;
  86. int subpage_size;
  87. int vid_hdr_offs;
  88. int ec;
  89. int ubi_ver;
  90. uint32_t image_seq;
  91. int verbose;
  92. dictionary *dict;
  93. };
  94. static struct args args = {
  95. .peb_size = -1,
  96. .min_io_size = -1,
  97. .subpage_size = -1,
  98. .ubi_ver = 1,
  99. };
  100. static int parse_opt(int argc, char * const argv[])
  101. {
  102. util_srand();
  103. args.image_seq = rand();
  104. while (1) {
  105. int key, error = 0;
  106. unsigned long int image_seq;
  107. key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhV", long_options, NULL);
  108. if (key == -1)
  109. break;
  110. switch (key) {
  111. case 'o':
  112. args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY,
  113. S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH);
  114. if (args.out_fd == -1)
  115. return sys_errmsg("cannot open file \"%s\"", optarg);
  116. args.f_out = optarg;
  117. break;
  118. case 'p':
  119. args.peb_size = util_get_bytes(optarg);
  120. if (args.peb_size <= 0)
  121. return errmsg("bad physical eraseblock size: \"%s\"", optarg);
  122. break;
  123. case 'm':
  124. args.min_io_size = util_get_bytes(optarg);
  125. if (args.min_io_size <= 0)
  126. return errmsg("bad min. I/O unit size: \"%s\"", optarg);
  127. if (!is_power_of_2(args.min_io_size))
  128. return errmsg("min. I/O unit size should be power of 2");
  129. break;
  130. case 's':
  131. args.subpage_size = util_get_bytes(optarg);
  132. if (args.subpage_size <= 0)
  133. return errmsg("bad sub-page size: \"%s\"", optarg);
  134. if (!is_power_of_2(args.subpage_size))
  135. return errmsg("sub-page size should be power of 2");
  136. break;
  137. case 'O':
  138. args.vid_hdr_offs = simple_strtoul(optarg, &error);
  139. if (error || args.vid_hdr_offs < 0)
  140. return errmsg("bad VID header offset: \"%s\"", optarg);
  141. break;
  142. case 'e':
  143. args.ec = simple_strtoul(optarg, &error);
  144. if (error || args.ec < 0)
  145. return errmsg("bad erase counter value: \"%s\"", optarg);
  146. break;
  147. case 'x':
  148. args.ubi_ver = simple_strtoul(optarg, &error);
  149. if (error || args.ubi_ver < 0)
  150. return errmsg("bad UBI version: \"%s\"", optarg);
  151. break;
  152. case 'Q':
  153. image_seq = simple_strtoul(optarg, &error);
  154. if (error || image_seq > 0xFFFFFFFF)
  155. return errmsg("bad UBI image sequence number: \"%s\"", optarg);
  156. args.image_seq = image_seq;
  157. break;
  158. case 'v':
  159. args.verbose = 1;
  160. break;
  161. case 'h':
  162. fputs(usage, stdout);
  163. fputs(optionsstr, stdout);
  164. printf("For more information see `man 8 %s`\n\n",
  165. PROGRAM_NAME);
  166. exit(EXIT_SUCCESS);
  167. case 'V':
  168. common_print_version();
  169. exit(EXIT_SUCCESS);
  170. default:
  171. fputs(usage, stderr);
  172. fputs("Use -h for help\n\n", stderr);
  173. return -1;
  174. }
  175. }
  176. if (optind == argc)
  177. return errmsg("input configuration file was not specified (use -h for help)");
  178. if (optind != argc - 1)
  179. return errmsg("more then one configuration file was specified (use -h for help)");
  180. args.f_in = argv[optind];
  181. if (args.peb_size < 0)
  182. return errmsg("physical eraseblock size was not specified (use -h for help)");
  183. if (args.peb_size > UBI_MAX_PEB_SZ)
  184. return errmsg("too high physical eraseblock size %d", args.peb_size);
  185. if (args.min_io_size < 0)
  186. return errmsg("min. I/O unit size was not specified (use -h for help)");
  187. if (args.subpage_size < 0)
  188. args.subpage_size = args.min_io_size;
  189. if (args.subpage_size > args.min_io_size)
  190. return errmsg("sub-page cannot be larger then min. I/O unit");
  191. if (args.peb_size % args.min_io_size)
  192. return errmsg("physical eraseblock should be multiple of min. I/O units");
  193. if (args.min_io_size % args.subpage_size)
  194. return errmsg("min. I/O unit size should be multiple of sub-page size");
  195. if (!args.f_out)
  196. return errmsg("output file was not specified (use -h for help)");
  197. if (args.vid_hdr_offs) {
  198. if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE >= args.peb_size)
  199. return errmsg("bad VID header position");
  200. if (args.vid_hdr_offs % 8)
  201. return errmsg("VID header offset has to be multiple of min. I/O unit size");
  202. }
  203. return 0;
  204. }
  205. static int read_section(const struct ubigen_info *ui, const char *sname,
  206. struct ubigen_vol_info *vi, const char **img,
  207. struct stat *st)
  208. {
  209. char buf[256];
  210. const char *p;
  211. *img = NULL;
  212. if (strlen(sname) > 128)
  213. return errmsg("too long section name \"%s\"", sname);
  214. /* Make sure mode is UBI, otherwise ignore this section */
  215. sprintf(buf, "%s:mode", sname);
  216. p = iniparser_getstring(args.dict, buf, NULL);
  217. if (!p) {
  218. errmsg("\"mode\" key not found in section \"%s\"", sname);
  219. errmsg("the \"mode\" key is mandatory and has to be "
  220. "\"mode=ubi\" if the section describes an UBI volume");
  221. return -1;
  222. }
  223. /* If mode is not UBI, skip this section */
  224. if (strcmp(p, "ubi")) {
  225. verbose(args.verbose, "skip non-ubi section \"%s\"", sname);
  226. return 1;
  227. }
  228. verbose(args.verbose, "mode=ubi, keep parsing");
  229. /* Fetch volume type */
  230. sprintf(buf, "%s:vol_type", sname);
  231. p = iniparser_getstring(args.dict, buf, NULL);
  232. if (!p) {
  233. normsg("volume type was not specified in "
  234. "section \"%s\", assume \"dynamic\"\n", sname);
  235. vi->type = UBI_VID_DYNAMIC;
  236. } else {
  237. if (!strcmp(p, "static"))
  238. vi->type = UBI_VID_STATIC;
  239. else if (!strcmp(p, "dynamic"))
  240. vi->type = UBI_VID_DYNAMIC;
  241. else
  242. return errmsg("invalid volume type \"%s\" in section \"%s\"",
  243. p, sname);
  244. }
  245. verbose(args.verbose, "volume type: %s",
  246. vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static");
  247. /* Fetch the name of the volume image file */
  248. sprintf(buf, "%s:image", sname);
  249. p = iniparser_getstring(args.dict, buf, NULL);
  250. if (p) {
  251. *img = p;
  252. if (stat(p, st))
  253. return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"",
  254. p, sname);
  255. if (st->st_size == 0)
  256. return errmsg("empty file \"%s\" referred from section \"%s\"",
  257. p, sname);
  258. } else if (vi->type == UBI_VID_STATIC)
  259. return errmsg("image is not specified for static volume in section \"%s\"",
  260. sname);
  261. /* Fetch volume id */
  262. sprintf(buf, "%s:vol_id", sname);
  263. vi->id = iniparser_getint(args.dict, buf, -1);
  264. if (vi->id == -1)
  265. return errmsg("\"vol_id\" key not found in section \"%s\"", sname);
  266. if (vi->id < 0)
  267. return errmsg("negative volume ID %d in section \"%s\"",
  268. vi->id, sname);
  269. if (vi->id >= ui->max_volumes)
  270. return errmsg("too high volume ID %d in section \"%s\", max. is %d",
  271. vi->id, sname, ui->max_volumes);
  272. verbose(args.verbose, "volume ID: %d", vi->id);
  273. /* Fetch volume size */
  274. sprintf(buf, "%s:vol_size", sname);
  275. p = iniparser_getstring(args.dict, buf, NULL);
  276. if (p) {
  277. vi->bytes = util_get_bytes(p);
  278. if (vi->bytes <= 0)
  279. return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")",
  280. p, sname);
  281. /* Make sure the image size is not larger than volume size */
  282. if (*img && st->st_size > vi->bytes)
  283. return errmsg("error in section \"%s\": size of the image file "
  284. "\"%s\" is %lld, which is larger than volume size %lld",
  285. sname, *img, (long long)st->st_size, vi->bytes);
  286. verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
  287. } else {
  288. struct stat st;
  289. if (!*img)
  290. return errmsg("neither image file (\"image=\") nor volume size "
  291. "(\"vol_size=\") specified in section \"%s\"", sname);
  292. if (stat(*img, &st))
  293. return sys_errmsg("cannot stat \"%s\"", *img);
  294. vi->bytes = st.st_size;
  295. if (vi->bytes == 0)
  296. return errmsg("file \"%s\" referred from section \"%s\" is empty",
  297. *img, sname);
  298. normsg_cont("volume size was not specified in section \"%s\", assume"
  299. " minimum to fit image \"%s\"", sname, *img);
  300. util_print_bytes(vi->bytes, 1);
  301. printf("\n");
  302. }
  303. /* Fetch volume name */
  304. sprintf(buf, "%s:vol_name", sname);
  305. p = iniparser_getstring(args.dict, buf, NULL);
  306. if (!p)
  307. return errmsg("\"vol_name\" key not found in section \"%s\"", sname);
  308. vi->name = p;
  309. vi->name_len = strlen(p);
  310. if (vi->name_len > UBI_VOL_NAME_MAX)
  311. return errmsg("too long volume name in section \"%s\", max. is %d characters",
  312. vi->name, UBI_VOL_NAME_MAX);
  313. verbose(args.verbose, "volume name: %s", p);
  314. /* Fetch volume alignment */
  315. sprintf(buf, "%s:vol_alignment", sname);
  316. vi->alignment = iniparser_getint(args.dict, buf, -1);
  317. if (vi->alignment == -1)
  318. vi->alignment = 1;
  319. else if (vi->id < 0)
  320. return errmsg("negative volume alignement %d in section \"%s\"",
  321. vi->alignment, sname);
  322. verbose(args.verbose, "volume alignment: %d", vi->alignment);
  323. /* Fetch volume flags */
  324. sprintf(buf, "%s:vol_flags", sname);
  325. p = iniparser_getstring(args.dict, buf, NULL);
  326. if (p) {
  327. /*
  328. * For now, the flag can be either autoresize or skip-check, as
  329. * skip-check is reserved for static volumes and autoresize for
  330. * such a volume makes no sense.
  331. * Once we add another flag that isn't incompatible with each
  332. * and every existing flag, we'll have to implement a solution
  333. * that allows multiple flags to be set at the same time in
  334. * vol_flags setting of the section.
  335. */
  336. if (!strcmp(p, "autoresize")) {
  337. verbose(args.verbose, "autoresize flags found");
  338. vi->flags |= UBI_VTBL_AUTORESIZE_FLG;
  339. } else if (!strcmp(p, "skip-check")) {
  340. verbose(args.verbose, "skip-check flag found");
  341. vi->flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG;
  342. } else {
  343. return errmsg("unknown flags \"%s\" in section \"%s\"",
  344. p, sname);
  345. }
  346. }
  347. /* Initialize the rest of the volume information */
  348. vi->data_pad = ui->leb_size % vi->alignment;
  349. vi->usable_leb_size = ui->leb_size - vi->data_pad;
  350. if (vi->type == UBI_VID_DYNAMIC)
  351. vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
  352. else
  353. vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
  354. vi->compat = 0;
  355. return 0;
  356. }
  357. int main(int argc, char * const argv[])
  358. {
  359. int err = -1, sects, i, autoresize_was_already = 0;
  360. struct ubigen_info ui;
  361. struct ubi_vtbl_record *vtbl;
  362. struct ubigen_vol_info *vi;
  363. off_t seek;
  364. err = parse_opt(argc, argv);
  365. if (err)
  366. return -1;
  367. ubigen_info_init(&ui, args.peb_size, args.min_io_size,
  368. args.subpage_size, args.vid_hdr_offs,
  369. args.ubi_ver, args.image_seq);
  370. verbose(args.verbose, "LEB size: %d", ui.leb_size);
  371. verbose(args.verbose, "PEB size: %d", ui.peb_size);
  372. verbose(args.verbose, "min. I/O size: %d", ui.min_io_size);
  373. verbose(args.verbose, "sub-page size: %d", args.subpage_size);
  374. verbose(args.verbose, "VID offset: %d", ui.vid_hdr_offs);
  375. verbose(args.verbose, "data offset: %d", ui.data_offs);
  376. verbose(args.verbose, "UBI image sequence number: %u", ui.image_seq);
  377. vtbl = ubigen_create_empty_vtbl(&ui);
  378. if (!vtbl) {
  379. err = -1;
  380. goto out;
  381. }
  382. args.dict = iniparser_load(args.f_in);
  383. if (!args.dict) {
  384. err = -1;
  385. errmsg("cannot load the input ini file \"%s\"", args.f_in);
  386. goto out_vtbl;
  387. }
  388. verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in);
  389. /* Each section describes one volume */
  390. sects = iniparser_getnsec(args.dict);
  391. if (sects == -1) {
  392. err = -1;
  393. errmsg("ini-file parsing error (iniparser_getnsec)");
  394. goto out_dict;
  395. }
  396. verbose(args.verbose, "count of sections: %d", sects);
  397. if (sects == 0) {
  398. err = -1;
  399. errmsg("no sections found the ini-file \"%s\"", args.f_in);
  400. goto out_dict;
  401. }
  402. if (sects > ui.max_volumes) {
  403. err = -1;
  404. errmsg("too many sections (%d) in the ini-file \"%s\"",
  405. sects, args.f_in);
  406. normsg("each section corresponds to an UBI volume, maximum "
  407. "count of volumes is %d", ui.max_volumes);
  408. goto out_dict;
  409. }
  410. vi = calloc(sizeof(struct ubigen_vol_info), sects);
  411. if (!vi) {
  412. err = -1;
  413. errmsg("cannot allocate memory");
  414. goto out_dict;
  415. }
  416. /*
  417. * Skip 2 PEBs at the beginning of the file for the volume table which
  418. * will be written later.
  419. */
  420. seek = ui.peb_size * 2;
  421. if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
  422. err = -1;
  423. sys_errmsg("cannot seek file \"%s\"", args.f_out);
  424. goto out_free;
  425. }
  426. for (i = 0; i < sects; i++) {
  427. const char *sname = iniparser_getsecname(args.dict, i);
  428. const char *img = NULL;
  429. struct stat st;
  430. int fd, j;
  431. if (!sname) {
  432. err = -1;
  433. errmsg("ini-file parsing error (iniparser_getsecname)");
  434. goto out_free;
  435. }
  436. if (args.verbose)
  437. printf("\n");
  438. verbose(args.verbose, "parsing section \"%s\"", sname);
  439. err = read_section(&ui, sname, &vi[i], &img, &st);
  440. if (err == -1)
  441. goto out_free;
  442. verbose(args.verbose, "adding volume %d", vi[i].id);
  443. /*
  444. * Make sure that volume ID and name is unique and that only
  445. * one volume has auto-resize flag
  446. */
  447. for (j = 0; j < i; j++) {
  448. if (vi[i].id == vi[j].id) {
  449. err = -1;
  450. errmsg("volume IDs must be unique, but ID %d "
  451. "in section \"%s\" is not",
  452. vi[i].id, sname);
  453. goto out_free;
  454. }
  455. if (!strcmp(vi[i].name, vi[j].name)) {
  456. err = -1;
  457. errmsg("volume name must be unique, but name "
  458. "\"%s\" in section \"%s\" is not",
  459. vi[i].name, sname);
  460. goto out_free;
  461. }
  462. }
  463. if (vi[i].flags & UBI_VTBL_SKIP_CRC_CHECK_FLG &&
  464. vi[i].type != UBI_VID_STATIC)
  465. return errmsg("skip-check is only valid for static volumes");
  466. if (vi[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
  467. if (autoresize_was_already)
  468. return errmsg("only one volume is allowed "
  469. "to have auto-resize flag");
  470. autoresize_was_already = 1;
  471. }
  472. err = ubigen_add_volume(&ui, &vi[i], vtbl);
  473. if (err) {
  474. errmsg("cannot add volume for section \"%s\"", sname);
  475. goto out_free;
  476. }
  477. if (img) {
  478. fd = open(img, O_RDONLY);
  479. if (fd == -1) {
  480. err = fd;
  481. sys_errmsg("cannot open \"%s\"", img);
  482. goto out_free;
  483. }
  484. verbose(args.verbose, "writing volume %d", vi[i].id);
  485. verbose(args.verbose, "image file: %s", img);
  486. err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd);
  487. close(fd);
  488. if (err) {
  489. errmsg("cannot write volume for section \"%s\"", sname);
  490. goto out_free;
  491. }
  492. }
  493. if (args.verbose)
  494. printf("\n");
  495. }
  496. verbose(args.verbose, "writing layout volume");
  497. err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
  498. if (err) {
  499. errmsg("cannot write layout volume");
  500. goto out_free;
  501. }
  502. verbose(args.verbose, "done");
  503. free(vi);
  504. iniparser_freedict(args.dict);
  505. free(vtbl);
  506. close(args.out_fd);
  507. return 0;
  508. out_free:
  509. free(vi);
  510. out_dict:
  511. iniparser_freedict(args.dict);
  512. out_vtbl:
  513. free(vtbl);
  514. out:
  515. close(args.out_fd);
  516. remove(args.f_out);
  517. return err;
  518. }