1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
28 #include "gigabeats.h"
30 #include "telechips.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
);
39 ARCHOS_PLAYER
, /* and V1 recorder */
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
)
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];
68 void int2le(unsigned int val
, unsigned char* addr
)
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;
84 void short2be(unsigned short val
, unsigned char* addr
)
86 addr
[0] = (val
>> 8) & 0xff;
92 printf("usage: scramble [options] <input file> <output file> [xor string]\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"
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, c100, clip, e2v2, m2v4,\n"
126 "\t fuze, c2v2, clv2, y820, y920, y925, x747, 747p, \n"
128 printf("\nNo option results in Archos standard player/recorder format.\n");
133 int main (int argc
, char** argv
)
135 unsigned long length
,i
,slen
=0;
136 unsigned char *inbuf
,*outbuf
;
137 unsigned short crc
=0;
138 unsigned long chksum
=0; /* 32 bit checksum */
139 unsigned char header
[24];
140 char *iname
= argv
[1];
141 char *oname
= argv
[2];
142 char *xorstring
=NULL
;
146 unsigned long modelnum
;
149 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
150 bool creative_enable_ciff
;
152 model_id
= ARCHOS_PLAYER
;
158 if(!strcmp(argv
[1], "-fm")) {
163 model_id
= ARCHOS_FMRECORDER
;
166 else if(!strcmp(argv
[1], "-v2")) {
171 model_id
= ARCHOS_V2RECORDER
;
174 else if(!strcmp(argv
[1], "-ofm")) {
179 model_id
= ARCHOS_ONDIO_FM
;
182 else if(!strcmp(argv
[1], "-osp")) {
187 model_id
= ARCHOS_ONDIO_SP
;
190 else if(!strcmp(argv
[1], "-neo")) {
196 else if(!strncmp(argv
[1], "-mm=", 4)) {
201 version
= argv
[1][4];
205 printf("Multimedia needs an xor string\n");
209 else if(!strncmp(argv
[1], "-tcc=", 4)) {
214 if(!strcmp(&argv
[1][5], "sum"))
216 else if(!strcmp(&argv
[1][5], "crc"))
219 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
223 else if(!strncmp(argv
[1], "-add=", 5)) {
228 if(!strcmp(&argv
[1][5], "h120"))
230 else if(!strcmp(&argv
[1][5], "h140"))
231 modelnum
= 0; /* the same as the h120 */
232 else if(!strcmp(&argv
[1][5], "h100"))
234 else if(!strcmp(&argv
[1][5], "h300"))
236 else if(!strcmp(&argv
[1][5], "ipco"))
238 else if(!strcmp(&argv
[1][5], "nano"))
240 else if(!strcmp(&argv
[1][5], "ipvd"))
242 else if(!strcmp(&argv
[1][5], "fp7x"))
244 else if(!strcmp(&argv
[1][5], "ip3g"))
246 else if(!strcmp(&argv
[1][5], "ip4g"))
248 else if(!strcmp(&argv
[1][5], "mini"))
250 else if(!strcmp(&argv
[1][5], "iax5"))
252 else if(!strcmp(&argv
[1][5], "mn2g"))
254 else if(!strcmp(&argv
[1][5], "h10"))
256 else if(!strcmp(&argv
[1][5], "h10_5gb"))
258 else if(!strcmp(&argv
[1][5], "tpj2"))
260 else if(!strcmp(&argv
[1][5], "e200"))
262 else if(!strcmp(&argv
[1][5], "iam5"))
264 else if(!strcmp(&argv
[1][5], "giga"))
266 else if(!strcmp(&argv
[1][5], "1g2g"))
268 else if(!strcmp(&argv
[1][5], "c200"))
270 else if(!strcmp(&argv
[1][5], "gigs"))
272 else if(!strcmp(&argv
[1][5], "m500"))
274 else if(!strcmp(&argv
[1][5], "m100"))
276 else if(!strcmp(&argv
[1][5], "d2"))
278 else if(!strcmp(&argv
[1][5], "iam3"))
280 else if (!strcmp(&argv
[1][5], "m200"))
282 else if(!strcmp(&argv
[1][5], "c100"))
284 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
286 else if (!strcmp(&argv
[1][5], "i7"))
288 else if (!strcmp(&argv
[1][5], "ldax"))
290 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
292 else if (!strcmp(&argv
[1][5], "clip"))
294 else if (!strcmp(&argv
[1][5], "e2v2"))
296 else if (!strcmp(&argv
[1][5], "m2v4"))
298 else if (!strcmp(&argv
[1][5], "fuze"))
300 else if (!strcmp(&argv
[1][5], "c2v2"))
302 else if (!strcmp(&argv
[1][5], "x747"))
304 else if (!strcmp(&argv
[1][5], "747p"))
306 else if (!strcmp(&argv
[1][5], "x777"))
308 else if (!strcmp(&argv
[1][5], "y820")) /* Samsung YH-820 */
310 else if (!strcmp(&argv
[1][5], "y920")) /* Samsung YH-920 */
312 else if (!strcmp(&argv
[1][5], "y925")) /* Samsung YH-925 */
314 else if (!strcmp(&argv
[1][5], "clv2")) /* Sansa Clipv2 */
317 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
320 /* we store a 4-letter model name too, for humans */
321 strcpy(modelname
, &argv
[1][5]);
322 chksum
= modelnum
; /* start checksum calcs with this */
325 else if(!strcmp(argv
[1], "-iriver")) {
326 /* iRiver code dealt with in the iriver.c code */
329 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
331 else if(!strcmp(argv
[1], "-gigabeat")) {
332 /* iRiver code dealt with in the iriver.c code */
335 gigabeat_code(iname
, oname
);
338 else if(!strcmp(argv
[1], "-gigabeats")) {
341 return gigabeat_s_code(iname
, oname
);
343 else if(!strcmp(argv
[1], "-iaudiox5")) {
346 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
348 else if(!strcmp(argv
[1], "-iaudiox5v")) {
351 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
353 else if(!strcmp(argv
[1], "-iaudiom5")) {
356 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
358 else if(!strcmp(argv
[1], "-iaudiom3")) {
361 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
363 else if(!strcmp(argv
[1], "-ipod3g")) {
366 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
368 else if(!strcmp(argv
[1], "-ipod4g")) {
371 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
373 else if(!strcmp(argv
[1], "-ipod5g")) {
376 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
378 else if(!strncmp(argv
[1], "-creative=", 10))
380 if(!strcmp(argv
[2], "-no-ciff"))
382 creative_enable_ciff
= false;
388 creative_enable_ciff
= true;
392 if(!strcmp(&argv
[1][10], "zvm"))
393 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
394 else if(!strcmp(&argv
[1][10], "zvm60"))
395 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
396 else if(!strcmp(&argv
[1][10], "zenvision"))
397 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
398 else if(!strcmp(&argv
[1][10], "zenv"))
399 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
400 else if(!strcmp(&argv
[1][10], "zen"))
401 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
404 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
408 else if(!strncmp(argv
[1], "-mi4", 4)) {
413 if(!strcmp(&argv
[1][4], "v2")) {
414 mi4magic
= MI4_MAGIC_DEFAULT
;
415 version
= 0x00010201;
417 else if(!strcmp(&argv
[1][4], "v3")) {
418 mi4magic
= MI4_MAGIC_DEFAULT
;
419 version
= 0x00010301;
421 else if(!strcmp(&argv
[1][4], "r")) {
422 mi4magic
= MI4_MAGIC_R
;
423 version
= 0x00010301;
426 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
433 if(!strncmp(argv
[2], "-model=", 7)) {
436 strncpy(model
, &argv
[2][7], 4);
438 if(!strncmp(argv
[3], "-type=", 6)) {
441 strncpy(type
, &argv
[3][6], 4);
445 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
449 file
= fopen(iname
,"rb");
454 fseek(file
,0,SEEK_END
);
455 length
= ftell(file
);
456 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
458 if ((method
== scramble
) &&
459 ((length
+ headerlen
) >= size_limit
[model_id
])) {
460 printf("error: firmware image is %ld bytes while max size is %u!\n",
462 size_limit
[model_id
]);
467 fseek(file
,0,SEEK_SET
);
468 inbuf
= malloc(length
);
470 outbuf
= malloc(length
*2);
471 else if(method
== add
)
472 outbuf
= malloc(length
+ 8);
474 outbuf
= malloc(length
);
475 if ( !inbuf
|| !outbuf
) {
476 printf("out of memory!\n");
480 /* zero-fill the last 4 bytes to make sure there's no rubbish there
481 when we write the size-aligned file later */
482 memset(outbuf
+length
-4, 0, 4);
486 i
=fread(inbuf
,1,length
,file
);
496 for (i
= 0; i
< length
; i
++) {
497 /* add 8 unsigned bits but keep a 32 bit sum */
503 for (i
= 0; i
< length
; i
++) {
504 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
505 unsigned char data
= inbuf
[i
];
506 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
514 for (i
=0; i
<length
; i
++) {
516 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
517 outbuf
[slen
++] = inbuf
[i
];
522 /* dummy case just to silence picky compilers */
526 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
527 /* calculate checksum */
528 for (i
=0;i
<length
;i
++)
532 memset(header
, 0, sizeof header
);
537 int2be(chksum
, header
); /* checksum, big-endian */
538 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
539 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
545 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
546 telechips_encode_sum(outbuf
, length
);
550 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
551 telechips_encode_crc(outbuf
, length
);
555 if (headerlen
== 6) {
556 int2be(length
, header
);
557 header
[4] = (crc
>> 8) & 0xff;
558 header
[5] = crc
& 0xff;
564 header
[3] = 0xff; /* ??? */
566 header
[6] = (crc
>> 8) & 0xff;
567 header
[7] = crc
& 0xff;
569 header
[11] = version
;
571 header
[15] = headerlen
; /* really? */
573 int2be(length
, &header
[20]);
579 int xorlen
= strlen(xorstring
);
582 for (i
=0; i
<slen
; i
++)
583 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
585 /* calculate checksum */
586 for (i
=0; i
<slen
; i
++)
589 header
[0] = header
[2] = 'Z';
590 header
[1] = header
[3] = version
;
591 int2le(length
, &header
[4]);
592 int2le(slen
, &header
[8]);
593 int2le(crc
, &header
[12]);
598 #define MY_FIRMWARE_TYPE "Rockbox"
599 #define MY_HEADER_VERSION 1
601 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
602 header
[9]='\0'; /*shouldn't have to, but to be SURE */
603 header
[10]=MY_HEADER_VERSION
&0xFF;
604 header
[11]=(crc
>>8)&0xFF;
606 int2be(sizeof(header
), &header
[12]);
611 file
= fopen(oname
,"wb");
617 if ( !fwrite(header
,headerlen
,1,file
) ) {
622 if ( !fwrite(outbuf
,length
,1,file
) ) {
634 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
639 unsigned char *outbuf
;
641 unsigned char sum
= 0;
643 file
= fopen(iname
, "rb");
648 fseek(file
,0,SEEK_END
);
649 length
= ftell(file
);
651 fseek(file
,0,SEEK_SET
);
652 outbuf
= malloc(length
+0x1030);
655 printf("out of memory!\n");
659 len
= fread(outbuf
+0x1030, 1, length
, file
);
660 if(len
< (size_t) length
) {
665 memset(outbuf
, 0, 0x1030);
666 strcpy((char *)outbuf
, idstring
);
667 memcpy(outbuf
+0x20, iaudio_bl_flash
,
668 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
669 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
670 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
673 for(i
= 0; i
< length
;i
++)
674 sum
+= outbuf
[0x1030 + i
];
676 int2be(length
, &outbuf
[0x1024]);
677 outbuf
[0x102b] = sum
;
681 file
= fopen(oname
, "wb");
687 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
688 if(len
< (size_t)length
) {
698 /* Create an ipod firmware partition image
700 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
702 This function doesn't yet handle the Broadcom resource image for the 5g,
703 so the resulting images won't be usable.
705 This has also only been tested on an ipod Photo
708 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
710 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
731 unsigned int sum
= 0;
732 unsigned int rsrcsum
= 0;
733 unsigned char *outbuf
;
737 file
= fopen(iname
, "rb");
742 fseek(file
,0,SEEK_END
);
743 length
= ftell(file
);
745 fseek(file
,0,SEEK_SET
);
747 bufsize
=(length
+0x4600);
749 bufsize
= (bufsize
+ 0x400) & ~0x200;
752 outbuf
= malloc(bufsize
);
755 printf("out of memory!\n");
759 len
= fread(outbuf
+0x4600, 1, length
, file
);
760 if(len
< (size_t)length
) {
766 /* Calculate checksum for later use in header */
767 for(i
= 0x4600; i
< 0x4600+length
;i
++)
770 /* Clear the header area to zero */
771 memset(outbuf
, 0, 0x4600);
773 /* APPLE STOP SIGN */
774 strcpy((char *)outbuf
, apple_stop_sign
);
777 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
778 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
779 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
780 short2le(fw_ver
, &outbuf
[0x10a]);
782 /* Firmware Directory - "osos" entry */
783 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
784 int2le(0, &outbuf
[0x4208]); /* id */
785 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
786 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
787 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
788 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
789 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
790 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
791 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
793 /* "rsrc" entry (if applicable) */
795 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
799 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
800 int2le(0, &outbuf
[0x4230]); /* id */
801 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
802 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
803 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
804 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
805 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
806 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
807 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
810 file
= fopen(oname
, "wb");
816 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
817 if(len
< (size_t)length
) {