Include divide-by-zero handling within plugins and codecs for ARM processors.
[kugel-rb.git] / tools / scramble.c
blob9fea89ce30f8a48019fa364cbc258bcd17a34d14
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 - 2007 by Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include "iriver.h"
27 #include "gigabeat.h"
28 #include "gigabeats.h"
29 #include "mi4.h"
30 #include "telechips.h"
31 #include "creative.h"
32 #include "iaudio_bl_flash.h"
34 int iaudio_encode(char *iname, char *oname, char *idstring);
35 int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc);
37 enum
39 ARCHOS_PLAYER, /* and V1 recorder */
40 ARCHOS_V2RECORDER,
41 ARCHOS_FMRECORDER,
42 ARCHOS_ONDIO_SP,
43 ARCHOS_ONDIO_FM
46 static unsigned int size_limit[] =
48 0x32000, /* ARCHOS_PLAYER */
49 0x64000, /* ARCHOS_V2RECORDER */
50 0x64000, /* ARCHOS_FMRECORDER */
51 0x64000, /* ARCHOS_ONDIO_SP */
52 0x64000 /* ARCHOS_ONDIO_FM */
55 void short2le(unsigned short val, unsigned char* addr)
57 addr[0] = val & 0xFF;
58 addr[1] = (val >> 8) & 0xff;
61 unsigned int le2int(unsigned char* buf)
63 unsigned int res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
65 return res;
68 void int2le(unsigned int val, unsigned char* addr)
70 addr[0] = val & 0xFF;
71 addr[1] = (val >> 8) & 0xff;
72 addr[2] = (val >> 16) & 0xff;
73 addr[3] = (val >> 24) & 0xff;
76 void int2be(unsigned int val, unsigned char* addr)
78 addr[0] = (val >> 24) & 0xff;
79 addr[1] = (val >> 16) & 0xff;
80 addr[2] = (val >> 8) & 0xff;
81 addr[3] = val & 0xFF;
84 void short2be(unsigned short val, unsigned char* addr)
86 addr[0] = (val >> 8) & 0xff;
87 addr[1] = val & 0xFF;
90 void usage(void)
92 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
93 printf("options:\n"
94 "\t-fm Archos FM recorder format\n"
95 "\t-v2 Archos V2 recorder format\n"
96 "\t-ofm Archos Ondio FM recorder format\n"
97 "\t-osp Archos Ondio SP format\n"
98 "\t-neo SSI Neo format\n"
99 "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n"
100 "\t-iriver iRiver format\n"
101 "\t-iaudiox5 iAudio X5 format\n"
102 "\t-iaudiox5v iAudio X5V format\n"
103 "\t-iaudiom5 iAudio M5 format\n"
104 "\t-iaudiom3 iAudio M3 format\n");
105 printf("\t-ipod3g ipod firmware partition format (3rd Gen)\n"
106 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
107 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
108 "\t-creative=X Creative firmware structure format\n"
109 "\t (X values: zvm, zvm60, zenvision\n"
110 "\t zenv, zen\n");
111 printf("\t-gigabeat Toshiba Gigabeat F/X format\n"
112 "\t-gigabeats Toshiba Gigabeat S format\n"
113 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
114 "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
115 "\t-mi4r Sandisk Rhapsody .mi4 format\n"
116 "\t All mi4 options take two optional arguments:\n");
117 printf("\t -model=XXXX where XXXX is the model id string\n"
118 "\t -type=XXXX where XXXX is a string indicating the \n"
119 "\t type of binary, eg. RBOS, RBBL\n"
120 "\t-tcc=X Telechips generic firmware format (X values: sum, crc)\n"
121 "\t-add=X Rockbox generic \"add-up\" checksum format\n"
122 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd, mn2g\n"
123 "\t ip3g, ip4g, mini, iax5, iam5, iam3, h10, h10_5gb,\n"
124 "\t tpj2, c200, e200, giga, gigs, m100, m500, d2,\n");
125 printf("\t 9200, 1630, ldax, m200, clip, e2v2, m2v4, fuze)\n");
126 printf("\nNo option results in Archos standard player/recorder format.\n");
128 exit(1);
131 int main (int argc, char** argv)
133 unsigned long length,i,slen=0;
134 unsigned char *inbuf,*outbuf;
135 unsigned short crc=0;
136 unsigned long chksum=0; /* 32 bit checksum */
137 unsigned char header[24];
138 char *iname = argv[1];
139 char *oname = argv[2];
140 char *xorstring=NULL;
141 int headerlen = 6;
142 FILE* file;
143 int version=0;
144 unsigned long modelnum;
145 char modelname[5];
146 int model_id;
147 enum { none, scramble, xor, tcc_sum, tcc_crc, add } method = scramble;
148 bool creative_enable_ciff;
150 model_id = ARCHOS_PLAYER;
152 if (argc < 3) {
153 usage();
156 if(!strcmp(argv[1], "-fm")) {
157 headerlen = 24;
158 iname = argv[2];
159 oname = argv[3];
160 version = 4;
161 model_id = ARCHOS_FMRECORDER;
164 else if(!strcmp(argv[1], "-v2")) {
165 headerlen = 24;
166 iname = argv[2];
167 oname = argv[3];
168 version = 2;
169 model_id = ARCHOS_V2RECORDER;
172 else if(!strcmp(argv[1], "-ofm")) {
173 headerlen = 24;
174 iname = argv[2];
175 oname = argv[3];
176 version = 8;
177 model_id = ARCHOS_ONDIO_FM;
180 else if(!strcmp(argv[1], "-osp")) {
181 headerlen = 24;
182 iname = argv[2];
183 oname = argv[3];
184 version = 16;
185 model_id = ARCHOS_ONDIO_SP;
188 else if(!strcmp(argv[1], "-neo")) {
189 headerlen = 17;
190 iname = argv[2];
191 oname = argv[3];
192 method = none;
194 else if(!strncmp(argv[1], "-mm=", 4)) {
195 headerlen = 16;
196 iname = argv[2];
197 oname = argv[3];
198 method = xor;
199 version = argv[1][4];
200 if (argc > 4)
201 xorstring = argv[4];
202 else {
203 printf("Multimedia needs an xor string\n");
204 return -1;
207 else if(!strncmp(argv[1], "-tcc=", 4)) {
208 headerlen = 0;
209 iname = argv[2];
210 oname = argv[3];
212 if(!strcmp(&argv[1][5], "sum"))
213 method = tcc_sum;
214 else if(!strcmp(&argv[1][5], "crc"))
215 method = tcc_crc;
216 else {
217 fprintf(stderr, "unsupported TCC method: %s\n", &argv[1][5]);
218 return 2;
221 else if(!strncmp(argv[1], "-add=", 5)) {
222 iname = argv[2];
223 oname = argv[3];
224 method = add;
226 if(!strcmp(&argv[1][5], "h120"))
227 modelnum = 0;
228 else if(!strcmp(&argv[1][5], "h140"))
229 modelnum = 0; /* the same as the h120 */
230 else if(!strcmp(&argv[1][5], "h100"))
231 modelnum = 1;
232 else if(!strcmp(&argv[1][5], "h300"))
233 modelnum = 2;
234 else if(!strcmp(&argv[1][5], "ipco"))
235 modelnum = 3;
236 else if(!strcmp(&argv[1][5], "nano"))
237 modelnum = 4;
238 else if(!strcmp(&argv[1][5], "ipvd"))
239 modelnum = 5;
240 else if(!strcmp(&argv[1][5], "fp7x"))
241 modelnum = 6;
242 else if(!strcmp(&argv[1][5], "ip3g"))
243 modelnum = 7;
244 else if(!strcmp(&argv[1][5], "ip4g"))
245 modelnum = 8;
246 else if(!strcmp(&argv[1][5], "mini"))
247 modelnum = 9;
248 else if(!strcmp(&argv[1][5], "iax5"))
249 modelnum = 10;
250 else if(!strcmp(&argv[1][5], "mn2g"))
251 modelnum = 11;
252 else if(!strcmp(&argv[1][5], "h10"))
253 modelnum = 13;
254 else if(!strcmp(&argv[1][5], "h10_5gb"))
255 modelnum = 14;
256 else if(!strcmp(&argv[1][5], "tpj2"))
257 modelnum = 15;
258 else if(!strcmp(&argv[1][5], "e200"))
259 modelnum = 16;
260 else if(!strcmp(&argv[1][5], "iam5"))
261 modelnum = 17;
262 else if(!strcmp(&argv[1][5], "giga"))
263 modelnum = 18;
264 else if(!strcmp(&argv[1][5], "1g2g"))
265 modelnum = 19;
266 else if(!strcmp(&argv[1][5], "c200"))
267 modelnum = 20;
268 else if(!strcmp(&argv[1][5], "gigs"))
269 modelnum = 21;
270 else if(!strcmp(&argv[1][5], "m500"))
271 modelnum = 22;
272 else if(!strcmp(&argv[1][5], "m100"))
273 modelnum = 23;
274 else if(!strcmp(&argv[1][5], "d2"))
275 modelnum = 24;
276 else if(!strcmp(&argv[1][5], "iam3"))
277 modelnum = 25;
278 else if (!strcmp(&argv[1][5], "m200"))
279 modelnum = 29;
280 else if(!strcmp(&argv[1][5], "1630")) /* Philips HDD1630 */
281 modelnum = 31;
282 else if (!strcmp(&argv[1][5], "i7"))
283 modelnum = 32;
284 else if (!strcmp(&argv[1][5], "ldax"))
285 modelnum = 33;
286 else if(!strcmp(&argv[1][5], "9200")) /* Philips SA9200 */
287 modelnum = 34;
288 else if (!strcmp(&argv[1][5], "clip"))
289 modelnum = 40;
290 else if (!strcmp(&argv[1][5], "e2v2"))
291 modelnum = 41;
292 else if (!strcmp(&argv[1][5], "m2v4"))
293 modelnum = 42;
294 else if (!strcmp(&argv[1][5], "fuze"))
295 modelnum = 43;
296 else if (!strcmp(&argv[1][5], "c2v2"))
297 modelnum = 44;
298 else {
299 fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
300 return 2;
302 /* we store a 4-letter model name too, for humans */
303 strcpy(modelname, &argv[1][5]);
304 chksum = modelnum; /* start checksum calcs with this */
307 else if(!strcmp(argv[1], "-iriver")) {
308 /* iRiver code dealt with in the iriver.c code */
309 iname = argv[2];
310 oname = argv[3];
311 return (iriver_encode(iname, oname, FALSE) != 0) ? -1 : 0;
313 else if(!strcmp(argv[1], "-gigabeat")) {
314 /* iRiver code dealt with in the iriver.c code */
315 iname = argv[2];
316 oname = argv[3];
317 gigabeat_code(iname, oname);
318 return 0;
320 else if(!strcmp(argv[1], "-gigabeats")) {
321 iname = argv[2];
322 oname = argv[3];
323 gigabeat_s_code(iname, oname);
324 return 0;
326 else if(!strcmp(argv[1], "-iaudiox5")) {
327 iname = argv[2];
328 oname = argv[3];
329 return iaudio_encode(iname, oname, "COWON_X5_FW");
331 else if(!strcmp(argv[1], "-iaudiox5v")) {
332 iname = argv[2];
333 oname = argv[3];
334 return iaudio_encode(iname, oname, "COWON_X5V_FW");
336 else if(!strcmp(argv[1], "-iaudiom5")) {
337 iname = argv[2];
338 oname = argv[3];
339 return iaudio_encode(iname, oname, "COWON_M5_FW");
341 else if(!strcmp(argv[1], "-iaudiom3")) {
342 iname = argv[2];
343 oname = argv[3];
344 return iaudio_encode(iname, oname, "COWON_M3_FW");
346 else if(!strcmp(argv[1], "-ipod3g")) {
347 iname = argv[2];
348 oname = argv[3];
349 return ipod_encode(iname, oname, 2, false); /* Firmware image v2 */
351 else if(!strcmp(argv[1], "-ipod4g")) {
352 iname = argv[2];
353 oname = argv[3];
354 return ipod_encode(iname, oname, 3, false); /* Firmware image v3 */
356 else if(!strcmp(argv[1], "-ipod5g")) {
357 iname = argv[2];
358 oname = argv[3];
359 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
361 else if(!strncmp(argv[1], "-creative=", 10))
363 if(!strcmp(argv[2], "-no-ciff"))
365 creative_enable_ciff = false;
366 iname = argv[3];
367 oname = argv[4];
369 else
371 creative_enable_ciff = true;
372 iname = argv[2];
373 oname = argv[3];
375 if(!strcmp(&argv[1][10], "zvm"))
376 return zvm_encode(iname, oname, ZENVISIONM, creative_enable_ciff);
377 else if(!strcmp(&argv[1][10], "zvm60"))
378 return zvm_encode(iname, oname, ZENVISIONM60, creative_enable_ciff);
379 else if(!strcmp(&argv[1][10], "zenvision"))
380 return zvm_encode(iname, oname, ZENVISION, creative_enable_ciff);
381 else if(!strcmp(&argv[1][10], "zenv"))
382 return zvm_encode(iname, oname, ZENV, creative_enable_ciff);
383 else if(!strcmp(&argv[1][10], "zen"))
384 return zvm_encode(iname, oname, ZEN, creative_enable_ciff);
385 else
387 fprintf(stderr, "unsupported Creative device: %s\n", &argv[1][10]);
388 return 2;
391 else if(!strncmp(argv[1], "-mi4", 4)) {
392 int mi4magic;
393 char model[4] = "";
394 char type[4] = "";
396 if(!strcmp(&argv[1][4], "v2")) {
397 mi4magic = MI4_MAGIC_DEFAULT;
398 version = 0x00010201;
400 else if(!strcmp(&argv[1][4], "v3")) {
401 mi4magic = MI4_MAGIC_DEFAULT;
402 version = 0x00010301;
404 else if(!strcmp(&argv[1][4], "r")) {
405 mi4magic = MI4_MAGIC_R;
406 version = 0x00010301;
408 else {
409 printf( "Invalid mi4 version: %s\n", &argv[1][4]);
410 return -1;
413 iname = argv[2];
414 oname = argv[3];
416 if(!strncmp(argv[2], "-model=", 7)) {
417 iname = argv[3];
418 oname = argv[4];
419 strncpy(model, &argv[2][7], 4);
421 if(!strncmp(argv[3], "-type=", 6)) {
422 iname = argv[4];
423 oname = argv[5];
424 strncpy(type, &argv[3][6], 4);
428 return mi4_encode(iname, oname, version, mi4magic, model, type);
431 /* open file */
432 file = fopen(iname,"rb");
433 if (!file) {
434 perror(iname);
435 return -1;
437 fseek(file,0,SEEK_END);
438 length = ftell(file);
439 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
441 if ((method == scramble) &&
442 ((length + headerlen) >= size_limit[model_id])) {
443 printf("error: firmware image is %ld bytes while max size is %u!\n",
444 length + headerlen,
445 size_limit[model_id]);
446 fclose(file);
447 return -1;
450 fseek(file,0,SEEK_SET);
451 inbuf = malloc(length);
452 if (method == xor)
453 outbuf = malloc(length*2);
454 else if(method == add)
455 outbuf = malloc(length + 8);
456 else
457 outbuf = malloc(length);
458 if ( !inbuf || !outbuf ) {
459 printf("out of memory!\n");
460 return -1;
462 if(length> 4) {
463 /* zero-fill the last 4 bytes to make sure there's no rubbish there
464 when we write the size-aligned file later */
465 memset(outbuf+length-4, 0, 4);
468 /* read file */
469 i=fread(inbuf,1,length,file);
470 if ( !i ) {
471 perror(iname);
472 return -1;
474 fclose(file);
476 switch (method)
478 case add:
479 for (i = 0; i < length; i++) {
480 /* add 8 unsigned bits but keep a 32 bit sum */
481 chksum += inbuf[i];
483 break;
484 case scramble:
485 slen = length/4;
486 for (i = 0; i < length; i++) {
487 unsigned long addr = (i >> 2) + ((i % 4) * slen);
488 unsigned char data = inbuf[i];
489 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
490 outbuf[addr] = data;
492 break;
494 case xor:
495 /* "compress" */
496 slen = 0;
497 for (i=0; i<length; i++) {
498 if (!(i&7))
499 outbuf[slen++] = 0xff; /* all data is uncompressed */
500 outbuf[slen++] = inbuf[i];
502 break;
503 case none:
504 default:
505 /* dummy case just to silence picky compilers */
506 break;
509 if((method == none) || (method == scramble) || (method == xor)) {
510 /* calculate checksum */
511 for (i=0;i<length;i++)
512 crc += inbuf[i];
515 memset(header, 0, sizeof header);
516 switch (method)
518 case add:
520 int2be(chksum, header); /* checksum, big-endian */
521 memcpy(&header[4], modelname, 4); /* 4 bytes model name */
522 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
523 headerlen = 8;
525 break;
527 case tcc_sum:
528 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
529 telechips_encode_sum(outbuf, length);
530 break;
532 case tcc_crc:
533 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
534 telechips_encode_crc(outbuf, length);
535 break;
537 case scramble:
538 if (headerlen == 6) {
539 int2be(length, header);
540 header[4] = (crc >> 8) & 0xff;
541 header[5] = crc & 0xff;
543 else {
544 header[0] =
545 header[1] =
546 header[2] =
547 header[3] = 0xff; /* ??? */
549 header[6] = (crc >> 8) & 0xff;
550 header[7] = crc & 0xff;
552 header[11] = version;
554 header[15] = headerlen; /* really? */
556 int2be(length, &header[20]);
558 break;
560 case xor:
562 int xorlen = strlen(xorstring);
564 /* xor data */
565 for (i=0; i<slen; i++)
566 outbuf[i] ^= xorstring[i & (xorlen-1)];
568 /* calculate checksum */
569 for (i=0; i<slen; i++)
570 crc += outbuf[i];
572 header[0] = header[2] = 'Z';
573 header[1] = header[3] = version;
574 int2le(length, &header[4]);
575 int2le(slen, &header[8]);
576 int2le(crc, &header[12]);
577 length = slen;
578 break;
581 #define MY_FIRMWARE_TYPE "Rockbox"
582 #define MY_HEADER_VERSION 1
583 default:
584 strncpy((char *)header, MY_FIRMWARE_TYPE,9);
585 header[9]='\0'; /*shouldn't have to, but to be SURE */
586 header[10]=MY_HEADER_VERSION&0xFF;
587 header[11]=(crc>>8)&0xFF;
588 header[12]=crc&0xFF;
589 int2be(sizeof(header), &header[12]);
590 break;
593 /* write file */
594 file = fopen(oname,"wb");
595 if ( !file ) {
596 perror(oname);
597 return -1;
599 if (headerlen > 0) {
600 if ( !fwrite(header,headerlen,1,file) ) {
601 perror(oname);
602 return -1;
605 if ( !fwrite(outbuf,length,1,file) ) {
606 perror(oname);
607 return -1;
609 fclose(file);
611 free(inbuf);
612 free(outbuf);
614 return 0;
617 int iaudio_encode(char *iname, char *oname, char *idstring)
619 size_t len;
620 int length;
621 FILE *file;
622 unsigned char *outbuf;
623 int i;
624 unsigned char sum = 0;
626 file = fopen(iname, "rb");
627 if (!file) {
628 perror(iname);
629 return -1;
631 fseek(file,0,SEEK_END);
632 length = ftell(file);
634 fseek(file,0,SEEK_SET);
635 outbuf = malloc(length+0x1030);
637 if ( !outbuf ) {
638 printf("out of memory!\n");
639 return -1;
642 len = fread(outbuf+0x1030, 1, length, file);
643 if(len < (size_t) length) {
644 perror(iname);
645 return -2;
648 memset(outbuf, 0, 0x1030);
649 strcpy((char *)outbuf, idstring);
650 memcpy(outbuf+0x20, iaudio_bl_flash,
651 BMPWIDTH_iaudio_bl_flash * (BMPHEIGHT_iaudio_bl_flash/8) * 2);
652 short2be(BMPWIDTH_iaudio_bl_flash, &outbuf[0x10]);
653 short2be((BMPHEIGHT_iaudio_bl_flash/8), &outbuf[0x12]);
654 outbuf[0x19] = 2;
656 for(i = 0; i < length;i++)
657 sum += outbuf[0x1030 + i];
659 int2be(length, &outbuf[0x1024]);
660 outbuf[0x102b] = sum;
662 fclose(file);
664 file = fopen(oname, "wb");
665 if (!file) {
666 perror(oname);
667 return -3;
670 len = fwrite(outbuf, 1, length+0x1030, file);
671 if(len < (size_t)length) {
672 perror(oname);
673 return -4;
676 fclose(file);
677 return 0;
681 /* Create an ipod firmware partition image
683 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
685 This function doesn't yet handle the Broadcom resource image for the 5g,
686 so the resulting images won't be usable.
688 This has also only been tested on an ipod Photo
691 int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc)
693 static const char *apple_stop_sign = "{{~~ /-----\\ "\
694 "{{~~ / \\ "\
695 "{{~~| | "\
696 "{{~~| S T O P | "\
697 "{{~~| | "\
698 "{{~~ \\ / "\
699 "{{~~ \\-----/ "\
700 "Copyright(C) 200"\
701 "1 Apple Computer"\
702 ", Inc.----------"\
703 "----------------"\
704 "----------------"\
705 "----------------"\
706 "----------------"\
707 "----------------"\
708 "---------------";
709 size_t len;
710 int length;
711 int rsrclength;
712 int rsrcoffset;
713 FILE *file;
714 unsigned int sum = 0;
715 unsigned int rsrcsum = 0;
716 unsigned char *outbuf;
717 int bufsize;
718 int i;
720 file = fopen(iname, "rb");
721 if (!file) {
722 perror(iname);
723 return -1;
725 fseek(file,0,SEEK_END);
726 length = ftell(file);
728 fseek(file,0,SEEK_SET);
730 bufsize=(length+0x4600);
731 if (fake_rsrc) {
732 bufsize = (bufsize + 0x400) & ~0x200;
735 outbuf = malloc(bufsize);
737 if ( !outbuf ) {
738 printf("out of memory!\n");
739 return -1;
742 len = fread(outbuf+0x4600, 1, length, file);
743 if(len < (size_t)length) {
744 perror(iname);
745 return -2;
747 fclose(file);
749 /* Calculate checksum for later use in header */
750 for(i = 0x4600; i < 0x4600+length;i++)
751 sum += outbuf[i];
753 /* Clear the header area to zero */
754 memset(outbuf, 0, 0x4600);
756 /* APPLE STOP SIGN */
757 strcpy((char *)outbuf, apple_stop_sign);
759 /* VOLUME HEADER */
760 memcpy(&outbuf[0x100],"]ih[",4); /* Magic */
761 int2le(0x4000, &outbuf[0x104]); /* Firmware offset relative to 0x200 */
762 short2le(0x10c, &outbuf[0x108]); /* Location of extended header */
763 short2le(fw_ver, &outbuf[0x10a]);
765 /* Firmware Directory - "osos" entry */
766 memcpy(&outbuf[0x4200],"!ATAsoso",8); /* dev and type */
767 int2le(0, &outbuf[0x4208]); /* id */
768 int2le(0x4400, &outbuf[0x420c]); /* devOffset */
769 int2le(length, &outbuf[0x4210]); /* Length of firmware */
770 int2le(0x10000000, &outbuf[0x4214]); /* Addr */
771 int2le(0, &outbuf[0x4218]); /* Entry Offset */
772 int2le(sum, &outbuf[0x421c]); /* Checksum */
773 int2le(0x00006012, &outbuf[0x4220]); /* vers - 0x6012 is a guess */
774 int2le(0xffffffff, &outbuf[0x4224]); /* LoadAddr - for flash images */
776 /* "rsrc" entry (if applicable) */
777 if (fake_rsrc) {
778 rsrcoffset=(length+0x4600+0x200) & ~0x200;
779 rsrclength=0x200;
780 rsrcsum=0;
782 memcpy(&outbuf[0x4228],"!ATAcrsr",8); /* dev and type */
783 int2le(0, &outbuf[0x4230]); /* id */
784 int2le(rsrcoffset, &outbuf[0x4234]); /* devOffset */
785 int2le(rsrclength, &outbuf[0x4238]); /* Length of firmware */
786 int2le(0x10000000, &outbuf[0x423c]); /* Addr */
787 int2le(0, &outbuf[0x4240]); /* Entry Offset */
788 int2le(rsrcsum, &outbuf[0x4244]); /* Checksum */
789 int2le(0x0000b000, &outbuf[0x4248]); /* vers */
790 int2le(0xffffffff, &outbuf[0x424c]); /* LoadAddr - for flash images */
793 file = fopen(oname, "wb");
794 if (!file) {
795 perror(oname);
796 return -3;
799 len = fwrite(outbuf, 1, length+0x4600, file);
800 if(len < (size_t)length) {
801 perror(oname);
802 return -4;
805 fclose(file);
807 return 0;