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