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"
129 "\t ip6g, rk27, clzp)\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+ */
340 else if (!strcmp(&argv
[1][5], "rk27")) /* rockchip 27xx generic */
342 else if (!strcmp(&argv
[1][5], "clzp")) /* Sansa Clip Zip */
345 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
348 /* we store a 4-letter model name too, for humans */
349 strncpy(modelname
, &argv
[1][5],4);
350 modelname
[4] = '\0'; /* to be sure we are null terminated */
351 chksum
= modelnum
; /* start checksum calcs with this */
354 else if(!strcmp(argv
[1], "-iriver")) {
355 /* iRiver code dealt with in the iriver.c code */
358 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
360 else if(!strcmp(argv
[1], "-gigabeat")) {
361 /* iRiver code dealt with in the iriver.c code */
364 gigabeat_code(iname
, oname
);
367 else if(!strcmp(argv
[1], "-gigabeats")) {
370 return gigabeat_s_code(iname
, oname
);
372 else if(!strcmp(argv
[1], "-iaudiox5")) {
375 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
377 else if(!strcmp(argv
[1], "-iaudiox5v")) {
380 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
382 else if(!strcmp(argv
[1], "-iaudiom5")) {
385 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
387 else if(!strcmp(argv
[1], "-iaudiom3")) {
390 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
392 else if(!strcmp(argv
[1], "-ipod3g")) {
395 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
397 else if(!strcmp(argv
[1], "-ipod4g")) {
400 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
402 else if(!strcmp(argv
[1], "-ipod5g")) {
405 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
407 else if(!strncmp(argv
[1], "-creative=", 10)) {
408 if(!strcmp(argv
[2], "-no-ciff"))
410 creative_enable_ciff
= false;
416 creative_enable_ciff
= true;
420 if(!strcmp(&argv
[1][10], "zvm"))
421 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
422 else if(!strcmp(&argv
[1][10], "zvm60"))
423 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
424 else if(!strcmp(&argv
[1][10], "zenvision"))
425 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
426 else if(!strcmp(&argv
[1][10], "zenv"))
427 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
428 else if(!strcmp(&argv
[1][10], "zen"))
429 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
432 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
436 else if(!strcmp(argv
[1], "-ccpmp")) {
439 return ccpmp_encode(iname
, oname
);
441 else if(!strncmp(argv
[1], "-mi4", 4)) {
446 if(!strcmp(&argv
[1][4], "v2")) {
447 mi4magic
= MI4_MAGIC_DEFAULT
;
448 version
= 0x00010201;
450 else if(!strcmp(&argv
[1][4], "v3")) {
451 mi4magic
= MI4_MAGIC_DEFAULT
;
452 version
= 0x00010301;
454 else if(!strcmp(&argv
[1][4], "r")) {
455 mi4magic
= MI4_MAGIC_R
;
456 version
= 0x00010301;
459 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
466 if(!strncmp(argv
[2], "-model=", 7)) {
469 strncpy(model
, &argv
[2][7], 4);
471 if(!strncmp(argv
[3], "-type=", 6)) {
474 strncpy(type
, &argv
[3][6], 4);
478 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
482 file
= fopen(iname
,"rb");
487 fseek(file
,0,SEEK_END
);
488 length
= ftell(file
);
489 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
491 if ((method
== scramble
) &&
492 ((length
+ headerlen
) >= size_limit
[model_id
])) {
493 printf("error: firmware image is %ld bytes while max size is %u!\n",
495 size_limit
[model_id
]);
500 fseek(file
,0,SEEK_SET
);
501 inbuf
= malloc(length
);
503 outbuf
= malloc(length
*2);
504 else if(method
== add
)
505 outbuf
= malloc(length
+ 8);
507 outbuf
= malloc(length
);
508 if ( !inbuf
|| !outbuf
) {
509 printf("out of memory!\n");
513 /* zero-fill the last 4 bytes to make sure there's no rubbish there
514 when we write the size-aligned file later */
515 memset(outbuf
+length
-4, 0, 4);
519 i
=fread(inbuf
,1,length
,file
);
529 for (i
= 0; i
< length
; i
++) {
530 /* add 8 unsigned bits but keep a 32 bit sum */
536 for (i
= 0; i
< length
; i
++) {
537 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
538 unsigned char data
= inbuf
[i
];
539 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
547 for (i
=0; i
<length
; i
++) {
549 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
550 outbuf
[slen
++] = inbuf
[i
];
555 /* dummy case just to silence picky compilers */
559 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
560 /* calculate checksum */
561 for (i
=0;i
<length
;i
++)
565 memset(header
, 0, sizeof header
);
570 int2be(chksum
, header
); /* checksum, big-endian */
571 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
572 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
578 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
579 telechips_encode_sum(outbuf
, length
);
583 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
584 telechips_encode_crc(outbuf
, length
);
588 if (headerlen
== 6) {
589 int2be(length
, header
);
590 header
[4] = (crc
>> 8) & 0xff;
591 header
[5] = crc
& 0xff;
597 header
[3] = 0xff; /* ??? */
599 header
[6] = (crc
>> 8) & 0xff;
600 header
[7] = crc
& 0xff;
602 header
[11] = version
;
604 header
[15] = headerlen
; /* really? */
606 int2be(length
, &header
[20]);
612 int xorlen
= strlen(xorstring
);
615 for (i
=0; i
<slen
; i
++)
616 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
618 /* calculate checksum */
619 for (i
=0; i
<slen
; i
++)
622 header
[0] = header
[2] = 'Z';
623 header
[1] = header
[3] = version
;
624 int2le(length
, &header
[4]);
625 int2le(slen
, &header
[8]);
626 int2le(crc
, &header
[12]);
631 #define MY_FIRMWARE_TYPE "Rockbox"
632 #define MY_HEADER_VERSION 1
634 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
635 header
[9]='\0'; /*shouldn't have to, but to be SURE */
636 header
[10]=MY_HEADER_VERSION
&0xFF;
637 header
[11]=(crc
>>8)&0xFF;
639 int2be(sizeof(header
), &header
[12]);
644 file
= fopen(oname
,"wb");
650 if ( !fwrite(header
,headerlen
,1,file
) ) {
655 if ( !fwrite(outbuf
,length
,1,file
) ) {
667 static int iaudio_encode(char *iname
, char *oname
, char *idstring
)
672 unsigned char *outbuf
;
674 unsigned char sum
= 0;
676 file
= fopen(iname
, "rb");
681 fseek(file
,0,SEEK_END
);
682 length
= ftell(file
);
684 fseek(file
,0,SEEK_SET
);
685 outbuf
= malloc(length
+0x1030);
688 printf("out of memory!\n");
692 len
= fread(outbuf
+0x1030, 1, length
, file
);
693 if(len
< (size_t) length
) {
698 memset(outbuf
, 0, 0x1030);
699 strcpy((char *)outbuf
, idstring
);
700 memcpy(outbuf
+0x20, iaudio_bl_flash
,
701 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
702 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
703 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
706 for(i
= 0; i
< length
;i
++)
707 sum
+= outbuf
[0x1030 + i
];
709 int2be(length
, &outbuf
[0x1024]);
710 outbuf
[0x102b] = sum
;
714 file
= fopen(oname
, "wb");
720 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
721 if(len
< (size_t)length
) {
731 /* Create an ipod firmware partition image
733 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
735 This function doesn't yet handle the Broadcom resource image for the 5g,
736 so the resulting images won't be usable.
738 This has also only been tested on an ipod Photo
741 static int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
743 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
764 unsigned int sum
= 0;
765 unsigned int rsrcsum
= 0;
766 unsigned char *outbuf
;
770 file
= fopen(iname
, "rb");
775 fseek(file
,0,SEEK_END
);
776 length
= ftell(file
);
778 fseek(file
,0,SEEK_SET
);
780 bufsize
=(length
+0x4600);
782 bufsize
= (bufsize
+ 0x400) & ~0x200;
785 outbuf
= malloc(bufsize
);
788 printf("out of memory!\n");
792 len
= fread(outbuf
+0x4600, 1, length
, file
);
793 if(len
< (size_t)length
) {
799 /* Calculate checksum for later use in header */
800 for(i
= 0x4600; i
< 0x4600+length
;i
++)
803 /* Clear the header area to zero */
804 memset(outbuf
, 0, 0x4600);
806 /* APPLE STOP SIGN */
807 strcpy((char *)outbuf
, apple_stop_sign
);
810 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
811 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
812 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
813 short2le(fw_ver
, &outbuf
[0x10a]);
815 /* Firmware Directory - "osos" entry */
816 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
817 int2le(0, &outbuf
[0x4208]); /* id */
818 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
819 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
820 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
821 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
822 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
823 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
824 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
826 /* "rsrc" entry (if applicable) */
828 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
832 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
833 int2le(0, &outbuf
[0x4230]); /* id */
834 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
835 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
836 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
837 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
838 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
839 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
840 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
843 file
= fopen(oname
, "wb");
849 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
850 if(len
< (size_t)length
) {
860 #define CCPMP_SIZE 0x500000
861 static int ccpmp_encode(char *iname
, char *oname
)
866 unsigned char *outbuf
;
868 file
= fopen(iname
, "rb");
873 fseek(file
,0,SEEK_END
);
874 length
= ftell(file
);
876 fseek(file
,0,SEEK_SET
);
878 outbuf
= malloc(CCPMP_SIZE
);
881 printf("out of memory!\n");
885 len
= fread(outbuf
, 1, length
, file
);
886 if(len
< (size_t)length
) {
892 /* Clear the tail area to 0xFF */
893 memset(&outbuf
[length
], 0xFF, CCPMP_SIZE
- length
);
896 int2le(length
, &outbuf
[0x4]);
898 file
= fopen(oname
, "wb");
904 len
= fwrite(outbuf
, 1, CCPMP_SIZE
, file
);
905 if(len
< (size_t)length
) {