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 */
339 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
342 /* we store a 4-letter model name too, for humans */
343 strncpy(modelname
, &argv
[1][5],4);
344 modelname
[4] = '\0'; /* to be sure we are null terminated */
345 chksum
= modelnum
; /* start checksum calcs with this */
348 else if(!strcmp(argv
[1], "-iriver")) {
349 /* iRiver code dealt with in the iriver.c code */
352 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
354 else if(!strcmp(argv
[1], "-gigabeat")) {
355 /* iRiver code dealt with in the iriver.c code */
358 gigabeat_code(iname
, oname
);
361 else if(!strcmp(argv
[1], "-gigabeats")) {
364 return gigabeat_s_code(iname
, oname
);
366 else if(!strcmp(argv
[1], "-iaudiox5")) {
369 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
371 else if(!strcmp(argv
[1], "-iaudiox5v")) {
374 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
376 else if(!strcmp(argv
[1], "-iaudiom5")) {
379 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
381 else if(!strcmp(argv
[1], "-iaudiom3")) {
384 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
386 else if(!strcmp(argv
[1], "-ipod3g")) {
389 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
391 else if(!strcmp(argv
[1], "-ipod4g")) {
394 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
396 else if(!strcmp(argv
[1], "-ipod5g")) {
399 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
401 else if(!strncmp(argv
[1], "-creative=", 10)) {
402 if(!strcmp(argv
[2], "-no-ciff"))
404 creative_enable_ciff
= false;
410 creative_enable_ciff
= true;
414 if(!strcmp(&argv
[1][10], "zvm"))
415 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
416 else if(!strcmp(&argv
[1][10], "zvm60"))
417 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
418 else if(!strcmp(&argv
[1][10], "zenvision"))
419 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
420 else if(!strcmp(&argv
[1][10], "zenv"))
421 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
422 else if(!strcmp(&argv
[1][10], "zen"))
423 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
426 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
430 else if(!strcmp(argv
[1], "-ccpmp")) {
433 return ccpmp_encode(iname
, oname
);
435 else if(!strncmp(argv
[1], "-mi4", 4)) {
440 if(!strcmp(&argv
[1][4], "v2")) {
441 mi4magic
= MI4_MAGIC_DEFAULT
;
442 version
= 0x00010201;
444 else if(!strcmp(&argv
[1][4], "v3")) {
445 mi4magic
= MI4_MAGIC_DEFAULT
;
446 version
= 0x00010301;
448 else if(!strcmp(&argv
[1][4], "r")) {
449 mi4magic
= MI4_MAGIC_R
;
450 version
= 0x00010301;
453 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
460 if(!strncmp(argv
[2], "-model=", 7)) {
463 strncpy(model
, &argv
[2][7], 4);
465 if(!strncmp(argv
[3], "-type=", 6)) {
468 strncpy(type
, &argv
[3][6], 4);
472 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
476 file
= fopen(iname
,"rb");
481 fseek(file
,0,SEEK_END
);
482 length
= ftell(file
);
483 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
485 if ((method
== scramble
) &&
486 ((length
+ headerlen
) >= size_limit
[model_id
])) {
487 printf("error: firmware image is %ld bytes while max size is %u!\n",
489 size_limit
[model_id
]);
494 fseek(file
,0,SEEK_SET
);
495 inbuf
= malloc(length
);
497 outbuf
= malloc(length
*2);
498 else if(method
== add
)
499 outbuf
= malloc(length
+ 8);
501 outbuf
= malloc(length
);
502 if ( !inbuf
|| !outbuf
) {
503 printf("out of memory!\n");
507 /* zero-fill the last 4 bytes to make sure there's no rubbish there
508 when we write the size-aligned file later */
509 memset(outbuf
+length
-4, 0, 4);
513 i
=fread(inbuf
,1,length
,file
);
523 for (i
= 0; i
< length
; i
++) {
524 /* add 8 unsigned bits but keep a 32 bit sum */
530 for (i
= 0; i
< length
; i
++) {
531 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
532 unsigned char data
= inbuf
[i
];
533 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
541 for (i
=0; i
<length
; i
++) {
543 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
544 outbuf
[slen
++] = inbuf
[i
];
549 /* dummy case just to silence picky compilers */
553 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
554 /* calculate checksum */
555 for (i
=0;i
<length
;i
++)
559 memset(header
, 0, sizeof header
);
564 int2be(chksum
, header
); /* checksum, big-endian */
565 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
566 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
572 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
573 telechips_encode_sum(outbuf
, length
);
577 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
578 telechips_encode_crc(outbuf
, length
);
582 if (headerlen
== 6) {
583 int2be(length
, header
);
584 header
[4] = (crc
>> 8) & 0xff;
585 header
[5] = crc
& 0xff;
591 header
[3] = 0xff; /* ??? */
593 header
[6] = (crc
>> 8) & 0xff;
594 header
[7] = crc
& 0xff;
596 header
[11] = version
;
598 header
[15] = headerlen
; /* really? */
600 int2be(length
, &header
[20]);
606 int xorlen
= strlen(xorstring
);
609 for (i
=0; i
<slen
; i
++)
610 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
612 /* calculate checksum */
613 for (i
=0; i
<slen
; i
++)
616 header
[0] = header
[2] = 'Z';
617 header
[1] = header
[3] = version
;
618 int2le(length
, &header
[4]);
619 int2le(slen
, &header
[8]);
620 int2le(crc
, &header
[12]);
625 #define MY_FIRMWARE_TYPE "Rockbox"
626 #define MY_HEADER_VERSION 1
628 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
629 header
[9]='\0'; /*shouldn't have to, but to be SURE */
630 header
[10]=MY_HEADER_VERSION
&0xFF;
631 header
[11]=(crc
>>8)&0xFF;
633 int2be(sizeof(header
), &header
[12]);
638 file
= fopen(oname
,"wb");
644 if ( !fwrite(header
,headerlen
,1,file
) ) {
649 if ( !fwrite(outbuf
,length
,1,file
) ) {
661 static int iaudio_encode(char *iname
, char *oname
, char *idstring
)
666 unsigned char *outbuf
;
668 unsigned char sum
= 0;
670 file
= fopen(iname
, "rb");
675 fseek(file
,0,SEEK_END
);
676 length
= ftell(file
);
678 fseek(file
,0,SEEK_SET
);
679 outbuf
= malloc(length
+0x1030);
682 printf("out of memory!\n");
686 len
= fread(outbuf
+0x1030, 1, length
, file
);
687 if(len
< (size_t) length
) {
692 memset(outbuf
, 0, 0x1030);
693 strcpy((char *)outbuf
, idstring
);
694 memcpy(outbuf
+0x20, iaudio_bl_flash
,
695 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
696 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
697 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
700 for(i
= 0; i
< length
;i
++)
701 sum
+= outbuf
[0x1030 + i
];
703 int2be(length
, &outbuf
[0x1024]);
704 outbuf
[0x102b] = sum
;
708 file
= fopen(oname
, "wb");
714 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
715 if(len
< (size_t)length
) {
725 /* Create an ipod firmware partition image
727 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
729 This function doesn't yet handle the Broadcom resource image for the 5g,
730 so the resulting images won't be usable.
732 This has also only been tested on an ipod Photo
735 static int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
737 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
758 unsigned int sum
= 0;
759 unsigned int rsrcsum
= 0;
760 unsigned char *outbuf
;
764 file
= fopen(iname
, "rb");
769 fseek(file
,0,SEEK_END
);
770 length
= ftell(file
);
772 fseek(file
,0,SEEK_SET
);
774 bufsize
=(length
+0x4600);
776 bufsize
= (bufsize
+ 0x400) & ~0x200;
779 outbuf
= malloc(bufsize
);
782 printf("out of memory!\n");
786 len
= fread(outbuf
+0x4600, 1, length
, file
);
787 if(len
< (size_t)length
) {
793 /* Calculate checksum for later use in header */
794 for(i
= 0x4600; i
< 0x4600+length
;i
++)
797 /* Clear the header area to zero */
798 memset(outbuf
, 0, 0x4600);
800 /* APPLE STOP SIGN */
801 strcpy((char *)outbuf
, apple_stop_sign
);
804 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
805 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
806 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
807 short2le(fw_ver
, &outbuf
[0x10a]);
809 /* Firmware Directory - "osos" entry */
810 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
811 int2le(0, &outbuf
[0x4208]); /* id */
812 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
813 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
814 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
815 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
816 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
817 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
818 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
820 /* "rsrc" entry (if applicable) */
822 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
826 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
827 int2le(0, &outbuf
[0x4230]); /* id */
828 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
829 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
830 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
831 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
832 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
833 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
834 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
837 file
= fopen(oname
, "wb");
843 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
844 if(len
< (size_t)length
) {
854 #define CCPMP_SIZE 0x500000
855 static int ccpmp_encode(char *iname
, char *oname
)
860 unsigned char *outbuf
;
862 file
= fopen(iname
, "rb");
867 fseek(file
,0,SEEK_END
);
868 length
= ftell(file
);
870 fseek(file
,0,SEEK_SET
);
872 outbuf
= malloc(CCPMP_SIZE
);
875 printf("out of memory!\n");
879 len
= fread(outbuf
, 1, length
, file
);
880 if(len
< (size_t)length
) {
886 /* Clear the tail area to 0xFF */
887 memset(&outbuf
[length
], 0xFF, CCPMP_SIZE
- length
);
890 int2le(length
, &outbuf
[0x4]);
892 file
= fopen(oname
, "wb");
898 len
= fwrite(outbuf
, 1, CCPMP_SIZE
, file
);
899 if(len
< (size_t)length
) {