OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | |||
31 | void |
||
32 | usage(void) |
||
33 | { |
||
34 | fprintf(stderr, "usage: lzma2eva <loadadddr> <entry> <lzmafile> <evafile>\n"); |
||
35 | exit(1); |
||
36 | } |
||
37 | |||
38 | void |
||
39 | pexit(const char *msg) |
||
40 | { |
||
41 | perror(msg); |
||
42 | exit(1); |
||
43 | } |
||
44 | |||
45 | int |
||
46 | main(int argc, char *argv[]) |
||
47 | { |
||
48 | |||
49 | const char *infile, *outfile; |
||
50 | FILE *in, *out; |
||
51 | static 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 | } |