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 static int iaudio_encode(char *iname
, char *oname
, char *idstring
);
35 static int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
);
36 static int ccpmp_encode(char *iname
, char *oname
);
40 ARCHOS_PLAYER
, /* and V1 recorder */
47 static unsigned int size_limit
[] =
49 0x32000, /* ARCHOS_PLAYER */
50 0x64000, /* ARCHOS_V2RECORDER */
51 0x64000, /* ARCHOS_FMRECORDER */
52 0x64000, /* ARCHOS_ONDIO_SP */
53 0x64000 /* ARCHOS_ONDIO_FM */
56 void short2le(unsigned short val
, unsigned char* addr
)
59 addr
[1] = (val
>> 8) & 0xff;
62 unsigned int le2int(unsigned char* buf
)
64 unsigned int res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
69 void int2le(unsigned int val
, unsigned char* addr
)
72 addr
[1] = (val
>> 8) & 0xff;
73 addr
[2] = (val
>> 16) & 0xff;
74 addr
[3] = (val
>> 24) & 0xff;
77 void int2be(unsigned int val
, unsigned char* addr
)
79 addr
[0] = (val
>> 24) & 0xff;
80 addr
[1] = (val
>> 16) & 0xff;
81 addr
[2] = (val
>> 8) & 0xff;
85 void short2be(unsigned short val
, unsigned char* addr
)
87 addr
[0] = (val
>> 8) & 0xff;
93 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
95 "\t-fm Archos FM recorder format\n"
96 "\t-v2 Archos V2 recorder format\n"
97 "\t-ofm Archos Ondio FM recorder format\n"
98 "\t-osp Archos Ondio SP format\n"
99 "\t-neo SSI Neo format\n"
100 "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n"
101 "\t-iriver iRiver format\n"
102 "\t-iaudiox5 iAudio X5 format\n"
103 "\t-iaudiox5v iAudio X5V format\n"
104 "\t-iaudiom5 iAudio M5 format\n"
105 "\t-iaudiom3 iAudio M3 format\n");
106 printf("\t-ipod3g ipod firmware partition format (3rd Gen)\n"
107 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
108 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
109 "\t-creative=X Creative firmware structure format\n"
110 "\t (X values: zvm, zvm60, zenvision\n"
112 printf("\t-gigabeat Toshiba Gigabeat F/X format\n"
113 "\t-gigabeats Toshiba Gigabeat S format\n"
114 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
115 "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
116 "\t-mi4r Sandisk Rhapsody .mi4 format\n"
117 "\t All mi4 options take two optional arguments:\n");
118 printf("\t -model=XXXX where XXXX is the model id string\n"
119 "\t -type=XXXX where XXXX is a string indicating the \n"
120 "\t type of binary, eg. RBOS, RBBL\n"
121 "\t-tcc=X Telechips generic firmware format (X values: sum, crc)\n"
122 "\t-add=X Rockbox generic \"add-up\" checksum format\n"
123 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd, mn2g\n"
124 "\t ip3g, ip4g, mini, iax5, iam5, iam3, h10, h10_5gb,\n"
125 "\t tpj2, c200, e200, giga, gigs, m100, m500, d2,\n");
126 printf("\t 9200, 1630, 6330, ldax, m200, c100, clip, e2v2,\n"
127 "\t m2v4, fuze, c2v2, clv2, y820, y920, y925, x747,\n"
128 "\t 747p, x777, nn2g, m244, cli+, fuz2, hd20, hd30,\n"
130 printf("\nNo option results in Archos standard player/recorder format.\n");
135 int main (int argc
, char** argv
)
137 unsigned long length
,i
,slen
=0;
138 unsigned char *inbuf
,*outbuf
;
139 unsigned short crc
=0;
140 unsigned long chksum
=0; /* 32 bit checksum */
141 unsigned char header
[24];
142 char *iname
= argv
[1];
143 char *oname
= argv
[2];
144 char *xorstring
=NULL
;
148 unsigned long modelnum
;
151 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
152 bool creative_enable_ciff
;
154 model_id
= ARCHOS_PLAYER
;
160 if(!strcmp(argv
[1], "-fm")) {
165 model_id
= ARCHOS_FMRECORDER
;
168 else if(!strcmp(argv
[1], "-v2")) {
173 model_id
= ARCHOS_V2RECORDER
;
176 else if(!strcmp(argv
[1], "-ofm")) {
181 model_id
= ARCHOS_ONDIO_FM
;
184 else if(!strcmp(argv
[1], "-osp")) {
189 model_id
= ARCHOS_ONDIO_SP
;
192 else if(!strcmp(argv
[1], "-neo")) {
198 else if(!strncmp(argv
[1], "-mm=", 4)) {
203 version
= argv
[1][4];
207 printf("Multimedia needs an xor string\n");
211 else if(!strncmp(argv
[1], "-tcc=", 4)) {
216 if(!strcmp(&argv
[1][5], "sum"))
218 else if(!strcmp(&argv
[1][5], "crc"))
221 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
225 else if(!strncmp(argv
[1], "-add=", 5)) {
230 if(!strcmp(&argv
[1][5], "h120"))
232 else if(!strcmp(&argv
[1][5], "h140"))
233 modelnum
= 0; /* the same as the h120 */
234 else if(!strcmp(&argv
[1][5], "h100"))
236 else if(!strcmp(&argv
[1][5], "h300"))
238 else if(!strcmp(&argv
[1][5], "ipco"))
240 else if(!strcmp(&argv
[1][5], "nano"))
242 else if(!strcmp(&argv
[1][5], "ipvd"))
244 else if(!strcmp(&argv
[1][5], "fp7x"))
246 else if(!strcmp(&argv
[1][5], "ip3g"))
248 else if(!strcmp(&argv
[1][5], "ip4g"))
250 else if(!strcmp(&argv
[1][5], "mini"))
252 else if(!strcmp(&argv
[1][5], "iax5"))
254 else if(!strcmp(&argv
[1][5], "mn2g"))
256 else if(!strcmp(&argv
[1][5], "h10"))
258 else if(!strcmp(&argv
[1][5], "h10_5gb"))
260 else if(!strcmp(&argv
[1][5], "tpj2"))
262 else if(!strcmp(&argv
[1][5], "e200"))
264 else if(!strcmp(&argv
[1][5], "iam5"))
266 else if(!strcmp(&argv
[1][5], "giga"))
268 else if(!strcmp(&argv
[1][5], "1g2g"))
270 else if(!strcmp(&argv
[1][5], "c200"))
272 else if(!strcmp(&argv
[1][5], "gigs"))
274 else if(!strcmp(&argv
[1][5], "m500"))
276 else if(!strcmp(&argv
[1][5], "m100"))
278 else if(!strcmp(&argv
[1][5], "d2"))
280 else if(!strcmp(&argv
[1][5], "iam3"))
282 else if (!strcmp(&argv
[1][5], "m200"))
284 else if(!strcmp(&argv
[1][5], "c100"))
286 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
288 else if (!strcmp(&argv
[1][5], "i7"))
290 else if (!strcmp(&argv
[1][5], "ldax"))
292 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
294 else if (!strcmp(&argv
[1][5], "clip"))
296 else if (!strcmp(&argv
[1][5], "e2v2"))
298 else if (!strcmp(&argv
[1][5], "m2v4"))
300 else if (!strcmp(&argv
[1][5], "fuze"))
302 else if (!strcmp(&argv
[1][5], "c2v2"))
304 else if (!strcmp(&argv
[1][5], "x747"))
306 else if (!strcmp(&argv
[1][5], "747p"))
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 */
316 else if (!strcmp(&argv
[1][5], "x777"))
318 else if (!strcmp(&argv
[1][5], "nn2g")) /* iPod Nano 2nd Gen */
320 else if (!strcmp(&argv
[1][5], "x767"))
322 else if (!strcmp(&argv
[1][5], "6330")) /* Philips HDD6330 */
324 else if (!strcmp(&argv
[1][5], "cli+")) /* Sansa Clip+ */
326 else if (!strcmp(&argv
[1][5], "v500")) /* Packard Bell Vibe 500 */
328 else if (!strcmp(&argv
[1][5], "fuz2")) /* Sansa Fuze v2 */
330 else if (!strcmp(&argv
[1][5], "m244"))
332 else if (!strcmp(&argv
[1][5], "hd20")) /* MPIO HD200 */
334 else if (!strcmp(&argv
[1][5], "hd30")) /* MPIO HD300 */
336 else if (!strcmp(&argv
[1][5], "ip6g")) /* iPod Classic/6G */
338 else if (!strcmp(&argv
[1][5], "fuz+")) /* Sansa Fuze+ */
341 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
344 /* we store a 4-letter model name too, for humans */
345 strncpy(modelname
, &argv
[1][5],4);
346 modelname
[4] = '\0'; /* to be sure we are null terminated */
347 chksum
= modelnum
; /* start checksum calcs with this */
350 else if(!strcmp(argv
[1], "-iriver")) {
351 /* iRiver code dealt with in the iriver.c code */
354 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
356 else if(!strcmp(argv
[1], "-gigabeat")) {
357 /* iRiver code dealt with in the iriver.c code */
360 gigabeat_code(iname
, oname
);
363 else if(!strcmp(argv
[1], "-gigabeats")) {
366 return gigabeat_s_code(iname
, oname
);
368 else if(!strcmp(argv
[1], "-iaudiox5")) {
371 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
373 else if(!strcmp(argv
[1], "-iaudiox5v")) {
376 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
378 else if(!strcmp(argv
[1], "-iaudiom5")) {
381 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
383 else if(!strcmp(argv
[1], "-iaudiom3")) {
386 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
388 else if(!strcmp(argv
[1], "-ipod3g")) {
391 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
393 else if(!strcmp(argv
[1], "-ipod4g")) {
396 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
398 else if(!strcmp(argv
[1], "-ipod5g")) {
401 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
403 else if(!strncmp(argv
[1], "-creative=", 10)) {
404 if(!strcmp(argv
[2], "-no-ciff"))
406 creative_enable_ciff
= false;
412 creative_enable_ciff
= true;
416 if(!strcmp(&argv
[1][10], "zvm"))
417 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
418 else if(!strcmp(&argv
[1][10], "zvm60"))
419 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
420 else if(!strcmp(&argv
[1][10], "zenvision"))
421 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
422 else if(!strcmp(&argv
[1][10], "zenv"))
423 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
424 else if(!strcmp(&argv
[1][10], "zen"))
425 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
428 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
432 else if(!strcmp(argv
[1], "-ccpmp")) {
435 return ccpmp_encode(iname
, oname
);
437 else if(!strncmp(argv
[1], "-mi4", 4)) {
442 if(!strcmp(&argv
[1][4], "v2")) {
443 mi4magic
= MI4_MAGIC_DEFAULT
;
444 version
= 0x00010201;
446 else if(!strcmp(&argv
[1][4], "v3")) {
447 mi4magic
= MI4_MAGIC_DEFAULT
;
448 version
= 0x00010301;
450 else if(!strcmp(&argv
[1][4], "r")) {
451 mi4magic
= MI4_MAGIC_R
;
452 version
= 0x00010301;
455 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
462 if(!strncmp(argv
[2], "-model=", 7)) {
465 strncpy(model
, &argv
[2][7], 4);
467 if(!strncmp(argv
[3], "-type=", 6)) {
470 strncpy(type
, &argv
[3][6], 4);
474 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
478 file
= fopen(iname
,"rb");
483 fseek(file
,0,SEEK_END
);
484 length
= ftell(file
);
485 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
487 if ((method
== scramble
) &&
488 ((length
+ headerlen
) >= size_limit
[model_id
])) {
489 printf("error: firmware image is %ld bytes while max size is %u!\n",
491 size_limit
[model_id
]);
496 fseek(file
,0,SEEK_SET
);
497 inbuf
= malloc(length
);
499 outbuf
= malloc(length
*2);
500 else if(method
== add
)
501 outbuf
= malloc(length
+ 8);
503 outbuf
= malloc(length
);
504 if ( !inbuf
|| !outbuf
) {
505 printf("out of memory!\n");
509 /* zero-fill the last 4 bytes to make sure there's no rubbish there
510 when we write the size-aligned file later */
511 memset(outbuf
+length
-4, 0, 4);
515 i
=fread(inbuf
,1,length
,file
);
525 for (i
= 0; i
< length
; i
++) {
526 /* add 8 unsigned bits but keep a 32 bit sum */
532 for (i
= 0; i
< length
; i
++) {
533 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
534 unsigned char data
= inbuf
[i
];
535 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
543 for (i
=0; i
<length
; i
++) {
545 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
546 outbuf
[slen
++] = inbuf
[i
];
551 /* dummy case just to silence picky compilers */
555 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
556 /* calculate checksum */
557 for (i
=0;i
<length
;i
++)
561 memset(header
, 0, sizeof header
);
566 int2be(chksum
, header
); /* checksum, big-endian */
567 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
568 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
574 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
575 telechips_encode_sum(outbuf
, length
);
579 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
580 telechips_encode_crc(outbuf
, length
);
584 if (headerlen
== 6) {
585 int2be(length
, header
);
586 header
[4] = (crc
>> 8) & 0xff;
587 header
[5] = crc
& 0xff;
593 header
[3] = 0xff; /* ??? */
595 header
[6] = (crc
>> 8) & 0xff;
596 header
[7] = crc
& 0xff;
598 header
[11] = version
;
600 header
[15] = headerlen
; /* really? */
602 int2be(length
, &header
[20]);
608 int xorlen
= strlen(xorstring
);
611 for (i
=0; i
<slen
; i
++)
612 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
614 /* calculate checksum */
615 for (i
=0; i
<slen
; i
++)
618 header
[0] = header
[2] = 'Z';
619 header
[1] = header
[3] = version
;
620 int2le(length
, &header
[4]);
621 int2le(slen
, &header
[8]);
622 int2le(crc
, &header
[12]);
627 #define MY_FIRMWARE_TYPE "Rockbox"
628 #define MY_HEADER_VERSION 1
630 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
631 header
[9]='\0'; /*shouldn't have to, but to be SURE */
632 header
[10]=MY_HEADER_VERSION
&0xFF;
633 header
[11]=(crc
>>8)&0xFF;
635 int2be(sizeof(header
), &header
[12]);
640 file
= fopen(oname
,"wb");
646 if ( !fwrite(header
,headerlen
,1,file
) ) {
651 if ( !fwrite(outbuf
,length
,1,file
) ) {
663 static int iaudio_encode(char *iname
, char *oname
, char *idstring
)
668 unsigned char *outbuf
;
670 unsigned char sum
= 0;
672 file
= fopen(iname
, "rb");
677 fseek(file
,0,SEEK_END
);
678 length
= ftell(file
);
680 fseek(file
,0,SEEK_SET
);
681 outbuf
= malloc(length
+0x1030);
684 printf("out of memory!\n");
688 len
= fread(outbuf
+0x1030, 1, length
, file
);
689 if(len
< (size_t) length
) {
694 memset(outbuf
, 0, 0x1030);
695 strcpy((char *)outbuf
, idstring
);
696 memcpy(outbuf
+0x20, iaudio_bl_flash
,
697 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
698 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
699 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
702 for(i
= 0; i
< length
;i
++)
703 sum
+= outbuf
[0x1030 + i
];
705 int2be(length
, &outbuf
[0x1024]);
706 outbuf
[0x102b] = sum
;
710 file
= fopen(oname
, "wb");
716 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
717 if(len
< (size_t)length
) {
727 /* Create an ipod firmware partition image
729 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
731 This function doesn't yet handle the Broadcom resource image for the 5g,
732 so the resulting images won't be usable.
734 This has also only been tested on an ipod Photo
737 static int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
739 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
760 unsigned int sum
= 0;
761 unsigned int rsrcsum
= 0;
762 unsigned char *outbuf
;
766 file
= fopen(iname
, "rb");
771 fseek(file
,0,SEEK_END
);
772 length
= ftell(file
);
774 fseek(file
,0,SEEK_SET
);
776 bufsize
=(length
+0x4600);
778 bufsize
= (bufsize
+ 0x400) & ~0x200;
781 outbuf
= malloc(bufsize
);
784 printf("out of memory!\n");
788 len
= fread(outbuf
+0x4600, 1, length
, file
);
789 if(len
< (size_t)length
) {
795 /* Calculate checksum for later use in header */
796 for(i
= 0x4600; i
< 0x4600+length
;i
++)
799 /* Clear the header area to zero */
800 memset(outbuf
, 0, 0x4600);
802 /* APPLE STOP SIGN */
803 strcpy((char *)outbuf
, apple_stop_sign
);
806 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
807 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
808 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
809 short2le(fw_ver
, &outbuf
[0x10a]);
811 /* Firmware Directory - "osos" entry */
812 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
813 int2le(0, &outbuf
[0x4208]); /* id */
814 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
815 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
816 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
817 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
818 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
819 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
820 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
822 /* "rsrc" entry (if applicable) */
824 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
828 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
829 int2le(0, &outbuf
[0x4230]); /* id */
830 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
831 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
832 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
833 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
834 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
835 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
836 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
839 file
= fopen(oname
, "wb");
845 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
846 if(len
< (size_t)length
) {
856 #define CCPMP_SIZE 0x500000
857 static int ccpmp_encode(char *iname
, char *oname
)
862 unsigned char *outbuf
;
864 file
= fopen(iname
, "rb");
869 fseek(file
,0,SEEK_END
);
870 length
= ftell(file
);
872 fseek(file
,0,SEEK_SET
);
874 outbuf
= malloc(CCPMP_SIZE
);
877 printf("out of memory!\n");
881 len
= fread(outbuf
, 1, length
, file
);
882 if(len
< (size_t)length
) {
888 /* Clear the tail area to 0xFF */
889 memset(&outbuf
[length
], 0xFF, CCPMP_SIZE
- length
);
892 int2le(length
, &outbuf
[0x4]);
894 file
= fopen(oname
, "wb");
900 len
= fwrite(outbuf
, 1, CCPMP_SIZE
, file
);
901 if(len
< (size_t)length
) {