wok annotate syslinux/stuff/iso2exe/iso2exe.c @ rev 17591

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