lzma2eva.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. lzma2eva - convert lzma-compressed file to AVM EVA bootloader format
  3. Copyright (C) 2007 Enrik Berkhan <Enrik.Berkhan@inka.de>
  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. 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.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. */
  16. #include <stdint.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <zlib.h> /* crc32 */
  20. #define checksum_add32(csum, data) \
  21. csum += ((uint8_t *)&data)[0]; \
  22. csum += ((uint8_t *)&data)[1]; \
  23. csum += ((uint8_t *)&data)[2]; \
  24. csum += ((uint8_t *)&data)[3];
  25. void
  26. usage(void)
  27. {
  28. fprintf(stderr, "usage: lzma2eva <loadadddr> <entry> <lzmafile> <evafile>\n");
  29. exit(1);
  30. }
  31. void
  32. pexit(const char *msg)
  33. {
  34. perror(msg);
  35. exit(1);
  36. }
  37. int
  38. main(int argc, char *argv[])
  39. {
  40. const char *infile, *outfile;
  41. FILE *in, *out;
  42. static const uint8_t buf[4096];
  43. size_t elems;
  44. uint8_t properties;
  45. uint32_t dictsize;
  46. uint64_t datasize;
  47. uint32_t magic = 0xfeed1281L;
  48. uint32_t reclength = 0;
  49. fpos_t reclengthpos;
  50. uint32_t loadaddress = 0;
  51. uint32_t type = 0x075a0201L; /* might be 7Z 2.1? */
  52. uint32_t checksum = 0;
  53. uint32_t compsize = 0;
  54. fpos_t compsizepos;
  55. uint32_t datasize32 = 0;
  56. uint32_t datacrc32 = crc32(0, 0, 0);
  57. uint32_t zero = 0;
  58. uint32_t entry = 0;
  59. if (argc != 5)
  60. usage();
  61. /* "parse" command line */
  62. loadaddress = strtoul(argv[1], 0, 0);
  63. entry = strtoul(argv[2], 0, 0);
  64. infile = argv[3];
  65. outfile = argv[4];
  66. in = fopen(infile, "rb");
  67. if (!in)
  68. pexit("fopen");
  69. out = fopen(outfile, "w+b");
  70. if (!out)
  71. pexit("fopen");
  72. /* read LZMA header */
  73. if (1 != fread(&properties, sizeof properties, 1, in))
  74. pexit("fread");
  75. if (1 != fread(&dictsize, sizeof dictsize, 1, in))
  76. pexit("fread");
  77. if (1 != fread(&datasize, sizeof datasize, 1, in))
  78. pexit("fread");
  79. /* write EVA header */
  80. if (1 != fwrite(&magic, sizeof magic, 1, out))
  81. pexit("fwrite");
  82. if (fgetpos(out, &reclengthpos))
  83. pexit("fgetpos");
  84. if (1 != fwrite(&reclength, sizeof reclength, 1, out))
  85. pexit("fwrite");
  86. if (1 != fwrite(&loadaddress, sizeof loadaddress, 1, out))
  87. pexit("fwrite");
  88. if (1 != fwrite(&type, sizeof type, 1, out))
  89. pexit("fwrite");
  90. /* write EVA LZMA header */
  91. if (fgetpos(out, &compsizepos))
  92. pexit("fgetpos");
  93. if (1 != fwrite(&compsize, sizeof compsize, 1, out))
  94. pexit("fwrite");
  95. /* XXX check length */
  96. datasize32 = (uint32_t)datasize;
  97. if (1 != fwrite(&datasize32, sizeof datasize32, 1, out))
  98. pexit("fwrite");
  99. if (1 != fwrite(&datacrc32, sizeof datacrc32, 1, out))
  100. pexit("fwrite");
  101. /* write modified LZMA header */
  102. if (1 != fwrite(&properties, sizeof properties, 1, out))
  103. pexit("fwrite");
  104. if (1 != fwrite(&dictsize, sizeof dictsize, 1, out))
  105. pexit("fwrite");
  106. if (1 != fwrite(&zero, 3, 1, out))
  107. pexit("fwrite");
  108. /* copy compressed data, calculate crc32 */
  109. while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, in))) {
  110. compsize += elems;
  111. if (elems != fwrite(&buf, sizeof buf[0], elems, out))
  112. pexit("fwrite");
  113. datacrc32 = crc32(datacrc32, buf, elems);
  114. }
  115. if (ferror(in))
  116. pexit("fread");
  117. fclose(in);
  118. /* re-write record length */
  119. reclength = compsize + 24;
  120. if (fsetpos(out, &reclengthpos))
  121. pexit("fsetpos");
  122. if (1 != fwrite(&reclength, sizeof reclength, 1, out))
  123. pexit("fwrite");
  124. /* re-write EVA LZMA header including size and data crc */
  125. if (fsetpos(out, &compsizepos))
  126. pexit("fsetpos");
  127. if (1 != fwrite(&compsize, sizeof compsize, 1, out))
  128. pexit("fwrite");
  129. if (1 != fwrite(&datasize32, sizeof datasize32, 1, out))
  130. pexit("fwrite");
  131. if (1 != fwrite(&datacrc32, sizeof datacrc32, 1, out))
  132. pexit("fwrite");
  133. /* calculate record checksum */
  134. checksum += reclength;
  135. checksum += loadaddress;
  136. checksum_add32(checksum, type);
  137. checksum_add32(checksum, compsize);
  138. checksum_add32(checksum, datasize32);
  139. checksum_add32(checksum, datacrc32);
  140. if (fseek(out, 0, SEEK_CUR))
  141. pexit("fseek");
  142. while (0 < (elems = fread(&buf, sizeof buf[0], sizeof buf, out))) {
  143. size_t i;
  144. for (i = 0; i < elems; ++i)
  145. checksum += buf[i];
  146. }
  147. if (ferror(out))
  148. pexit("fread");
  149. if (fseek(out, 0, SEEK_CUR))
  150. pexit("fseek");
  151. checksum = ~checksum + 1;
  152. if (1 != fwrite(&checksum, sizeof checksum, 1, out))
  153. pexit("fwrite");
  154. /* write entry record */
  155. if (1 != fwrite(&zero, sizeof zero, 1, out))
  156. pexit("fwrite");
  157. if (1 != fwrite(&entry, sizeof entry, 1, out))
  158. pexit("fwrite");
  159. if (fclose(out))
  160. pexit("fclose");
  161. return 0;
  162. }