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