wok-next view syslinux/stuff/iso2exe/iso2exe.c @ rev 18672
syslinux/iso2exe: undo custom config too
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sat Dec 05 12:23:18 2015 +0100 (2015-12-05) |
parents | 24b07aa2fafd |
children | ea9f391548cf |
line source
1 #ifdef __TURBOC__
2 #include <io.h>
3 #endif
4 #include <sys/types.h>
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #ifdef WIN32
10 #include <windows.h>
11 #endif
12 typedef unsigned char uint8_t;
13 typedef unsigned long uint32_t;
14 #include "iso2exe.h"
16 static int fd, forced, uninstall, status = 1;
17 static char tazlitoinfo[0x8000U - BOOTISOSZ];
18 #define buffer tazlitoinfo
19 #define BUFFERSZ 2048
20 #define WORD(n) * (unsigned short *) (n)
21 #define LONG(n) * (unsigned long *) (n)
23 static void readsector(unsigned long sector)
24 {
25 if (lseek(fd, sector * BUFFERSZ, SEEK_SET) == -1 ||
26 read(fd, buffer, BUFFERSZ) != BUFFERSZ) {
27 puts(bootiso+READSECTORERR);
28 exit(1);
29 }
30 }
32 static int skipmd5 = 0;
33 #define ALIGN1
35 typedef struct {
36 uint32_t l;
37 uint32_t h;
38 } uint64_t;
39 static uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */
40 static uint64_t total64; /* must be directly before hash[] */
41 static uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */
43 //#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
44 static uint32_t rotl32(uint32_t x, unsigned n)
45 {
46 return (x << n) | (x >> (32 - n));
47 }
49 static void md5_process_block64(void);
51 /* Feed data through a temporary buffer.
52 * The internal buffer remembers previous data until it has 64
53 * bytes worth to pass on.
54 */
55 static void common64_hash(const void *buffer, size_t len)
56 {
57 unsigned bufpos = total64.l & 63;
59 total64.l += len; if (total64.l < len) total64.h++;
61 while (1) {
62 unsigned remaining = 64 - bufpos;
63 if (remaining > len)
64 remaining = len;
65 /* Copy data into aligned buffer */
66 memcpy(wbuffer + bufpos, buffer, remaining);
67 len -= remaining;
68 buffer = (const char *)buffer + remaining;
69 bufpos += remaining;
70 /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */
71 bufpos -= 64;
72 if (bufpos != 0)
73 break;
74 /* Buffer is filled up, process it */
75 md5_process_block64();
76 /*bufpos = 0; - already is */
77 }
78 }
80 /* Process the remaining bytes in the buffer */
81 static void common64_end(void)
82 {
83 unsigned bufpos = total64.l & 63;
84 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
85 wbuffer[bufpos++] = 0x80;
87 /* This loop iterates either once or twice, no more, no less */
88 while (1) {
89 unsigned remaining = 64 - bufpos;
90 memset(wbuffer + bufpos, 0, remaining);
91 /* Do we have enough space for the length count? */
92 if (remaining >= 8) {
93 /* Store the 64-bit counter of bits in the buffer */
94 //uint64_t t = total64 << 3;
95 uint32_t *t = (uint32_t *) (&wbuffer[64 - 8]);
96 /* wbuffer is suitably aligned for this */
97 //*(uint64_t *) (&wbuffer[64 - 8]) = t;
98 t[0] = total64.l << 3;
99 t[1] = (total64.h << 3) | (total64.l >> 29);
100 }
101 md5_process_block64();
102 if (remaining >= 8)
103 break;
104 bufpos = 0;
105 }
106 }
108 /* These are the four functions used in the four steps of the MD5 algorithm
109 * and defined in the RFC 1321. The first function is a little bit optimized
110 * (as found in Colin Plumbs public domain implementation).
111 * #define FF(b, c, d) ((b & c) | (~b & d))
112 */
113 #undef FF
114 #undef FG
115 #undef FH
116 #undef FI
117 #define FF(b, c, d) (d ^ (b & (c ^ d)))
118 #define FG(b, c, d) FF(d, b, c)
119 #define FH(b, c, d) (b ^ c ^ d)
120 #define FI(b, c, d) (c ^ (b | ~d))
122 /* Hash a single block, 64 bytes long and 4-byte aligned */
123 static void md5_process_block64(void)
124 {
125 uint32_t *words = (void*) wbuffer;
126 uint32_t A = hash[0];
127 uint32_t B = hash[1];
128 uint32_t C = hash[2];
129 uint32_t D = hash[3];
131 const uint32_t *pc;
132 const char *pp;
133 const char *ps;
134 int i;
135 uint32_t temp;
138 pc = C_array;
139 pp = P_array;
140 ps = S_array - 4;
142 for (i = 0; i < 64; i++) {
143 if ((i & 0x0f) == 0)
144 ps += 4;
145 temp = A;
146 switch (i >> 4) {
147 case 0:
148 temp += FF(B, C, D);
149 break;
150 case 1:
151 temp += FG(B, C, D);
152 break;
153 case 2:
154 temp += FH(B, C, D);
155 break;
156 case 3:
157 temp += FI(B, C, D);
158 }
159 temp += words[(int) (*pp++)] + *pc++;
160 temp = rotl32(temp, ps[i & 3]);
161 temp += B;
162 A = D;
163 D = C;
164 C = B;
165 B = temp;
166 }
167 /* Add checksum to the starting values */
168 hash[0] += A;
169 hash[1] += B;
170 hash[2] += C;
171 hash[3] += D;
173 }
174 #undef FF
175 #undef FG
176 #undef FH
177 #undef FI
179 /* Initialize structure containing state of computation.
180 * (RFC 1321, 3.3: Step 3)
181 */
182 static void md5_begin(void)
183 {
184 hash[0] = 0x67452301;
185 hash[1] = 0xefcdab89;
186 hash[2] = 0x98badcfe;
187 hash[3] = 0x10325476;
188 total64.l = total64.h = 0;
189 }
191 /* Used also for sha1 and sha256 */
192 #define md5_hash common64_hash
194 /* Process the remaining bytes in the buffer and put result from CTX
195 * in first 16 bytes following RESBUF. The result is always in little
196 * endian byte order, so that a byte-wise output yields to the wanted
197 * ASCII representation of the message digest.
198 */
199 #define md5_end common64_end
201 static void md5sum(void)
202 {
203 unsigned long sectors = 0;
204 int count;
206 lseek(fd, 32768UL, SEEK_SET);
208 md5_begin();
209 while ((count = read(fd, buffer, BUFFERSZ)) > 0) {
210 if (sectors == 0)
211 sectors = LONG(buffer + 80);
212 md5_hash(buffer, count);
213 if (--sectors == 0)
214 break;
215 }
217 if (count < 0)
218 return;
220 md5_end();
222 lseek(fd, 32752UL, SEEK_SET);
223 write(fd, hash, 16);
224 memcpy(bootiso + BOOTISOSZ - 16, hash, 16);
225 }
227 static unsigned chksum(unsigned start, unsigned stop)
228 {
229 unsigned i, n = 0;
231 lseek(fd, 0UL /* (unsigned long) (start / BUFFERSZ) */, SEEK_SET);
232 while (1) {
233 if (read(fd, buffer, BUFFERSZ) != BUFFERSZ)
234 return 0;
235 for (i = start % BUFFERSZ; i < BUFFERSZ; i += 2, start += 2) {
236 if (start >= stop)
237 return - n;
238 n += WORD(buffer + i);
239 }
240 }
241 }
243 static unsigned install(char *filename)
244 {
245 #define heads 64
246 #define sectors 32
247 #define partition (446+16)
248 #define trksz (512UL * heads * sectors)
249 unsigned long size, catalog, lba;
250 int cylinders, i, j, isohybrid;
251 unsigned n;
252 #ifndef WIN32
253 for (bootiso = (char *) install;
254 bootiso[0] != 'M' || bootiso[1] != 'Z' || bootiso[2] != '\xEB';
255 bootiso++) if (bootiso < (char *) install) {
256 bootiso = "No bootiso data";
257 return 0;
258 }
259 #endif
260 if (!filename)
261 return USAGE;
262 fd = open(filename,O_RDWR|O_BINARY);
263 if (fd == -1)
264 return OPENERR;
266 if (uninstall) {
267 struct { char check[sizeof(tazlitoinfo) - BUFFERSZ - 1024]; };
268 readsector(0UL);
269 n = BUFFERSZ;
270 if (WORD(buffer) == 23117) {
271 readsector((unsigned long) buffer[417]);
272 n = 0;
273 }
274 lseek(fd, 0UL, SEEK_SET);
275 for (i = 0; i < 32; i++, n = BUFFERSZ) {
276 write(fd, buffer + n, 1024);
277 }
278 close(fd);
279 status = 0;
280 return UNINSTALLMSG;
281 }
283 if (forced == 0) {
284 status = 2;
285 /* Install hybridiso boot sector */
286 readsector(17UL);
287 if (strncmp(buffer+7, bootiso+ELTORITOERR+ELTORITOOFS, 23))
288 return ELTORITOERR;
289 catalog = LONG(buffer + 71);
290 readsector(catalog);
291 if (LONG(buffer) != 1 || LONG(buffer + 30) != 0x88AA55UL)
292 return CATALOGERR;
293 lba = LONG(buffer + 40);
294 readsector(lba);
295 if (LONG(buffer + 64) != 1886961915UL)
296 return HYBRIDERR;
297 isohybrid = bootiso[417] * 512;
298 LONG(bootiso + isohybrid + 432) = lba * 4;
299 LONG(bootiso + isohybrid + 440) = rand();
300 LONG(bootiso + isohybrid + partition) = 0x10080UL;
301 WORD(bootiso + isohybrid + 510) = 0xAA55U;
302 #if 0
303 size = lseek(fd, 0UL, SEEK_END);
304 size += 0x000FFFFFUL;
305 size &= 0xFFF00000UL;
306 #else
307 for (size = 0x000FFFFFUL; /* 1M - 1 */
308 read(fd, tazlitoinfo, 1024) == 1024;
309 size += 1024);
310 size &= 0xFFF00000UL; /* round */
311 #endif
312 cylinders = (size >> 20) - 1;
313 bootiso[isohybrid + partition + 4] = 23; /* "Windows hidden IFS" */
314 bootiso[isohybrid + partition + 5] = heads - 1;
315 bootiso[isohybrid + partition + 6] = ((cylinders & 0x300) >> 2) + sectors;
316 bootiso[isohybrid + partition + 7] = cylinders & 0xFF;
317 LONG(bootiso + isohybrid + partition + 8) = 0;
318 LONG(bootiso + isohybrid + partition + 12) = (size >> 9);
320 /* Copy the partition table */
321 memcpy(bootiso + 0x1BE, bootiso + isohybrid + 0x1BE, 66);
322 }
324 /* Install iso2exe boot sector */
325 LONG(bootiso + 440) = time(NULL);
327 /* read tazlito flavor data */
328 lseek(fd, 1024UL, SEEK_SET);
329 read(fd, tazlitoinfo, sizeof(tazlitoinfo));
331 /* Update iso image */
332 n = (bootiso[417] + 1) * 512;
333 lseek(fd, 0UL, SEEK_SET);
334 write(fd, bootiso, n); /* EXE/PE + isohybrid mbr */
335 write(fd, tazlitoinfo, sizeof(tazlitoinfo));
336 write(fd, bootiso + n, BOOTISOSZ - n); /* COM + rootfs + EXE/DOS */
338 /* Compute the boot checksums */
339 if (!skipmd5) {
340 puts(bootiso + MD5MSG);
341 md5sum();
342 lseek(fd, 0UL, SEEK_SET);
343 write(fd, bootiso, 512);
344 n = WORD(bootiso + 2) - 512*(WORD(bootiso + 4) - 1);
345 WORD(bootiso + 18) = chksum(0, (unsigned short) n) - 1;
346 }
347 lseek(fd, 0UL, SEEK_SET);
348 write(fd, bootiso, 512);
349 close(fd);
350 status = 0;
351 return SUCCESSMSG;
352 }
354 int main(int argc, char *argv[])
355 {
356 int i;
357 for (i = 2; i < argc; i++) {
358 char *s = argv[i];
359 while ((unsigned)(*s - '-') <= ('/' - '-')) s++;
360 switch (*s | 0x20) {
361 case 'f' : forced++; break;
362 case 'q' : skipmd5++; break;
363 case 'u' : uninstall++; break;
364 }
365 }
366 puts(bootiso + install(argv[1]));
367 if (status > 1)
368 puts(bootiso + FORCEMSG);
369 #ifdef WIN32
370 Sleep(2000);
371 #endif
372 return status;
373 }