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+ */
340 else if (!strcmp(&argv
[1][5], "rk27")) /* rockchip 27xx generic */
343 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
346 /* we store a 4-letter model name too, for humans */
347 strncpy(modelname
, &argv
[1][5],4);
348 modelname
[4] = '\0'; /* to be sure we are null terminated */
349 chksum
= modelnum
; /* start checksum calcs with this */
352 else if(!strcmp(argv
[1], "-iriver")) {
353 /* iRiver code dealt with in the iriver.c code */
356 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
358 else if(!strcmp(argv
[1], "-gigabeat")) {
359 /* iRiver code dealt with in the iriver.c code */
362 gigabeat_code(iname
, oname
);
365 else if(!strcmp(argv
[1], "-gigabeats")) {
368 return gigabeat_s_code(iname
, oname
);
370 else if(!strcmp(argv
[1], "-iaudiox5")) {
373 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
375 else if(!strcmp(argv
[1], "-iaudiox5v")) {
378 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
380 else if(!strcmp(argv
[1], "-iaudiom5")) {
383 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
385 else if(!strcmp(argv
[1], "-iaudiom3")) {
388 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
390 else if(!strcmp(argv
[1], "-ipod3g")) {
393 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
395 else if(!strcmp(argv
[1], "-ipod4g")) {
398 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
400 else if(!strcmp(argv
[1], "-ipod5g")) {
403 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
405 else if(!strncmp(argv
[1], "-creative=", 10)) {
406 if(!strcmp(argv
[2], "-no-ciff"))
408 creative_enable_ciff
= false;
414 creative_enable_ciff
= true;
418 if(!strcmp(&argv
[1][10], "zvm"))
419 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
420 else if(!strcmp(&argv
[1][10], "zvm60"))
421 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
422 else if(!strcmp(&argv
[1][10], "zenvision"))
423 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
424 else if(!strcmp(&argv
[1][10], "zenv"))
425 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
426 else if(!strcmp(&argv
[1][10], "zen"))
427 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
430 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
434 else if(!strcmp(argv
[1], "-ccpmp")) {
437 return ccpmp_encode(iname
, oname
);
439 else if(!strncmp(argv
[1], "-mi4", 4)) {
444 if(!strcmp(&argv
[1][4], "v2")) {
445 mi4magic
= MI4_MAGIC_DEFAULT
;
446 version
= 0x00010201;
448 else if(!strcmp(&argv
[1][4], "v3")) {
449 mi4magic
= MI4_MAGIC_DEFAULT
;
450 version
= 0x00010301;
452 else if(!strcmp(&argv
[1][4], "r")) {
453 mi4magic
= MI4_MAGIC_R
;
454 version
= 0x00010301;
457 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
464 if(!strncmp(argv
[2], "-model=", 7)) {
467 strncpy(model
, &argv
[2][7], 4);
469 if(!strncmp(argv
[3], "-type=", 6)) {
472 strncpy(type
, &argv
[3][6], 4);
476 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
480 file
= fopen(iname
,"rb");
485 fseek(file
,0,SEEK_END
);
486 length
= ftell(file
);
487 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
489 if ((method
== scramble
) &&
490 ((length
+ headerlen
) >= size_limit
[model_id
])) {
491 printf("error: firmware image is %ld bytes while max size is %u!\n",
493 size_limit
[model_id
]);
498 fseek(file
,0,SEEK_SET
);
499 inbuf
= malloc(length
);
501 outbuf
= malloc(length
*2);
502 else if(method
== add
)
503 outbuf
= malloc(length
+ 8);
505 outbuf
= malloc(length
);
506 if ( !inbuf
|| !outbuf
) {
507 printf("out of memory!\n");
511 /* zero-fill the last 4 bytes to make sure there's no rubbish there
512 when we write the size-aligned file later */
513 memset(outbuf
+length
-4, 0, 4);
517 i
=fread(inbuf
,1,length
,file
);
527 for (i
= 0; i
< length
; i
++) {
528 /* add 8 unsigned bits but keep a 32 bit sum */
534 for (i
= 0; i
< length
; i
++) {
535 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
536 unsigned char data
= inbuf
[i
];
537 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
545 for (i
=0; i
<length
; i
++) {
547 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
548 outbuf
[slen
++] = inbuf
[i
];
553 /* dummy case just to silence picky compilers */
557 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
558 /* calculate checksum */
559 for (i
=0;i
<length
;i
++)
563 memset(header
, 0, sizeof header
);
568 int2be(chksum
, header
); /* checksum, big-endian */
569 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
570 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
576 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
577 telechips_encode_sum(outbuf
, length
);
581 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
582 telechips_encode_crc(outbuf
, length
);
586 if (headerlen
== 6) {
587 int2be(length
, header
);
588 header
[4] = (crc
>> 8) & 0xff;
589 header
[5] = crc
& 0xff;
595 header
[3] = 0xff; /* ??? */
597 header
[6] = (crc
>> 8) & 0xff;
598 header
[7] = crc
& 0xff;
600 header
[11] = version
;
602 header
[15] = headerlen
; /* really? */
604 int2be(length
, &header
[20]);
610 int xorlen
= strlen(xorstring
);
613 for (i
=0; i
<slen
; i
++)
614 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
616 /* calculate checksum */
617 for (i
=0; i
<slen
; i
++)
620 header
[0] = header
[2] = 'Z';
621 header
[1] = header
[3] = version
;
622 int2le(length
, &header
[4]);
623 int2le(slen
, &header
[8]);
624 int2le(crc
, &header
[12]);
629 #define MY_FIRMWARE_TYPE "Rockbox"
630 #define MY_HEADER_VERSION 1
632 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
633 header
[9]='\0'; /*shouldn't have to, but to be SURE */
634 header
[10]=MY_HEADER_VERSION
&0xFF;
635 header
[11]=(crc
>>8)&0xFF;
637 int2be(sizeof(header
), &header
[12]);
642 file
= fopen(oname
,"wb");
648 if ( !fwrite(header
,headerlen
,1,file
) ) {
653 if ( !fwrite(outbuf
,length
,1,file
) ) {
665 static int iaudio_encode(char *iname
, char *oname
, char *idstring
)
670 unsigned char *outbuf
;
672 unsigned char sum
= 0;
674 file
= fopen(iname
, "rb");
679 fseek(file
,0,SEEK_END
);
680 length
= ftell(file
);
682 fseek(file
,0,SEEK_SET
);
683 outbuf
= malloc(length
+0x1030);
686 printf("out of memory!\n");
690 len
= fread(outbuf
+0x1030, 1, length
, file
);
691 if(len
< (size_t) length
) {
696 memset(outbuf
, 0, 0x1030);
697 strcpy((char *)outbuf
, idstring
);
698 memcpy(outbuf
+0x20, iaudio_bl_flash
,
699 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
700 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
701 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
704 for(i
= 0; i
< length
;i
++)
705 sum
+= outbuf
[0x1030 + i
];
707 int2be(length
, &outbuf
[0x1024]);
708 outbuf
[0x102b] = sum
;
712 file
= fopen(oname
, "wb");
718 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
719 if(len
< (size_t)length
) {
729 /* Create an ipod firmware partition image
731 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
733 This function doesn't yet handle the Broadcom resource image for the 5g,
734 so the resulting images won't be usable.
736 This has also only been tested on an ipod Photo
739 static int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
741 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
762 unsigned int sum
= 0;
763 unsigned int rsrcsum
= 0;
764 unsigned char *outbuf
;
768 file
= fopen(iname
, "rb");
773 fseek(file
,0,SEEK_END
);
774 length
= ftell(file
);
776 fseek(file
,0,SEEK_SET
);
778 bufsize
=(length
+0x4600);
780 bufsize
= (bufsize
+ 0x400) & ~0x200;
783 outbuf
= malloc(bufsize
);
786 printf("out of memory!\n");
790 len
= fread(outbuf
+0x4600, 1, length
, file
);
791 if(len
< (size_t)length
) {
797 /* Calculate checksum for later use in header */
798 for(i
= 0x4600; i
< 0x4600+length
;i
++)
801 /* Clear the header area to zero */
802 memset(outbuf
, 0, 0x4600);
804 /* APPLE STOP SIGN */
805 strcpy((char *)outbuf
, apple_stop_sign
);
808 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
809 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
810 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
811 short2le(fw_ver
, &outbuf
[0x10a]);
813 /* Firmware Directory - "osos" entry */
814 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
815 int2le(0, &outbuf
[0x4208]); /* id */
816 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
817 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
818 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
819 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
820 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
821 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
822 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
824 /* "rsrc" entry (if applicable) */
826 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
830 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
831 int2le(0, &outbuf
[0x4230]); /* id */
832 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
833 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
834 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
835 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
836 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
837 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
838 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
841 file
= fopen(oname
, "wb");
847 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
848 if(len
< (size_t)length
) {
858 #define CCPMP_SIZE 0x500000
859 static int ccpmp_encode(char *iname
, char *oname
)
864 unsigned char *outbuf
;
866 file
= fopen(iname
, "rb");
871 fseek(file
,0,SEEK_END
);
872 length
= ftell(file
);
874 fseek(file
,0,SEEK_SET
);
876 outbuf
= malloc(CCPMP_SIZE
);
879 printf("out of memory!\n");
883 len
= fread(outbuf
, 1, length
, file
);
884 if(len
< (size_t)length
) {
890 /* Clear the tail area to 0xFF */
891 memset(&outbuf
[length
], 0xFF, CCPMP_SIZE
- length
);
894 int2le(length
, &outbuf
[0x4]);
896 file
= fopen(oname
, "wb");
902 len
= fwrite(outbuf
, 1, CCPMP_SIZE
, file
);
903 if(len
< (size_t)length
) {