mkwrgimg.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
  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
  6. * by the Free Software Foundation.
  7. *
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <stdint.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <libgen.h>
  15. #include <getopt.h>
  16. #include <stdarg.h>
  17. #include <errno.h>
  18. #include <sys/stat.h>
  19. #include "md5.h"
  20. #define ERR(fmt, ...) do { \
  21. fflush(0); \
  22. fprintf(stderr, "[%s] *** error: " fmt "\n", \
  23. progname, ## __VA_ARGS__ ); \
  24. } while (0)
  25. #define ERRS(fmt, ...) do { \
  26. int save = errno; \
  27. fflush(0); \
  28. fprintf(stderr, "[%s] *** error: " fmt ", %s\n", \
  29. progname, ## __VA_ARGS__, strerror(save)); \
  30. } while (0)
  31. #define WRG_MAGIC 0x20040220
  32. struct wrg_header {
  33. char signature[32];
  34. uint32_t magic1;
  35. uint32_t magic2;
  36. uint32_t size;
  37. uint32_t offset;
  38. char devname[32];
  39. char digest[16];
  40. } __attribute__ ((packed));
  41. static char *progname;
  42. static char *ifname;
  43. static char *ofname;
  44. static char *signature;
  45. static char *dev_name;
  46. static uint32_t offset;
  47. static int big_endian;
  48. void usage(int status)
  49. {
  50. FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
  51. fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
  52. fprintf(stream,
  53. "\n"
  54. "Options:\n"
  55. " -b create image in big endian format\n"
  56. " -i <file> read input from the file <file>\n"
  57. " -d <name> set device name to <name>\n"
  58. " -o <file> write output to the file <file>\n"
  59. " -O <offset> set offset to <offset>\n"
  60. " -s <sig> set image signature to <sig>\n"
  61. " -h show this screen\n"
  62. );
  63. exit(status);
  64. }
  65. static void put_u32(void *data, uint32_t val)
  66. {
  67. unsigned char *p = data;
  68. if (big_endian) {
  69. p[0] = (val >> 24) & 0xff;
  70. p[1] = (val >> 16) & 0xff;
  71. p[2] = (val >> 8) & 0xff;
  72. p[3] = val & 0xff;
  73. } else {
  74. p[3] = (val >> 24) & 0xff;
  75. p[2] = (val >> 16) & 0xff;
  76. p[1] = (val >> 8) & 0xff;
  77. p[0] = val & 0xff;
  78. }
  79. }
  80. static void get_digest(struct wrg_header *header, char *data, int size)
  81. {
  82. MD5_CTX ctx;
  83. MD5_Init(&ctx);
  84. MD5_Update(&ctx, (char *)&header->offset, sizeof(header->offset));
  85. MD5_Update(&ctx, (char *)&header->devname, sizeof(header->devname));
  86. MD5_Update(&ctx, data, size);
  87. MD5_Final(header->digest, &ctx);
  88. }
  89. int main(int argc, char *argv[])
  90. {
  91. struct wrg_header *header;
  92. char *buf;
  93. struct stat st;
  94. int buflen;
  95. int err;
  96. int res = EXIT_FAILURE;
  97. FILE *outfile, *infile;
  98. progname = basename(argv[0]);
  99. while ( 1 ) {
  100. int c;
  101. c = getopt(argc, argv, "bd:i:o:s:O:h");
  102. if (c == -1)
  103. break;
  104. switch (c) {
  105. case 'b':
  106. big_endian = 1;
  107. break;
  108. case 'd':
  109. dev_name = optarg;
  110. break;
  111. case 'i':
  112. ifname = optarg;
  113. break;
  114. case 'o':
  115. ofname = optarg;
  116. break;
  117. case 's':
  118. signature = optarg;
  119. break;
  120. case 'O':
  121. offset = strtoul(optarg, NULL, 0);
  122. break;
  123. case 'h':
  124. usage(EXIT_SUCCESS);
  125. break;
  126. default:
  127. usage(EXIT_FAILURE);
  128. break;
  129. }
  130. }
  131. if (signature == NULL) {
  132. ERR("no signature specified");
  133. goto err;
  134. }
  135. if (ifname == NULL) {
  136. ERR("no input file specified");
  137. goto err;
  138. }
  139. if (ofname == NULL) {
  140. ERR("no output file specified");
  141. goto err;
  142. }
  143. if (dev_name == NULL) {
  144. ERR("no device name specified");
  145. goto err;
  146. }
  147. err = stat(ifname, &st);
  148. if (err){
  149. ERRS("stat failed on %s", ifname);
  150. goto err;
  151. }
  152. buflen = st.st_size + sizeof(struct wrg_header);
  153. buf = malloc(buflen);
  154. if (!buf) {
  155. ERR("no memory for buffer\n");
  156. goto err;
  157. }
  158. infile = fopen(ifname, "r");
  159. if (infile == NULL) {
  160. ERRS("could not open \"%s\" for reading", ifname);
  161. goto err_free;
  162. }
  163. errno = 0;
  164. fread(buf + sizeof(struct wrg_header), st.st_size, 1, infile);
  165. if (errno != 0) {
  166. ERRS("unable to read from file %s", ifname);
  167. goto close_in;
  168. }
  169. header = (struct wrg_header *) buf;
  170. memset(header, '\0', sizeof(struct wrg_header));
  171. strncpy(header->signature, signature, sizeof(header->signature));
  172. strncpy(header->devname, dev_name, sizeof(header->signature));
  173. put_u32(&header->magic1, WRG_MAGIC);
  174. put_u32(&header->magic2, WRG_MAGIC);
  175. put_u32(&header->size, st.st_size);
  176. put_u32(&header->offset, offset);
  177. get_digest(header, buf + sizeof(struct wrg_header), st.st_size);
  178. outfile = fopen(ofname, "w");
  179. if (outfile == NULL) {
  180. ERRS("could not open \"%s\" for writing", ofname);
  181. goto close_in;
  182. }
  183. errno = 0;
  184. fwrite(buf, buflen, 1, outfile);
  185. if (errno) {
  186. ERRS("unable to write to file %s", ofname);
  187. goto close_out;
  188. }
  189. fflush(outfile);
  190. res = EXIT_SUCCESS;
  191. close_out:
  192. fclose(outfile);
  193. if (res != EXIT_SUCCESS)
  194. unlink(ofname);
  195. close_in:
  196. fclose(infile);
  197. err_free:
  198. free(buf);
  199. err:
  200. return res;
  201. }