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, clip, e2v2, m2v4, fuze,\n"
126 "\t c2v2, clv2, y820, y920, y925)\n");
127 printf("\nNo option results in Archos standard player/recorder format.\n");
132 int main (int argc
, char** argv
)
134 unsigned long length
,i
,slen
=0;
135 unsigned char *inbuf
,*outbuf
;
136 unsigned short crc
=0;
137 unsigned long chksum
=0; /* 32 bit checksum */
138 unsigned char header
[24];
139 char *iname
= argv
[1];
140 char *oname
= argv
[2];
141 char *xorstring
=NULL
;
145 unsigned long modelnum
;
148 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
149 bool creative_enable_ciff
;
151 model_id
= ARCHOS_PLAYER
;
157 if(!strcmp(argv
[1], "-fm")) {
162 model_id
= ARCHOS_FMRECORDER
;
165 else if(!strcmp(argv
[1], "-v2")) {
170 model_id
= ARCHOS_V2RECORDER
;
173 else if(!strcmp(argv
[1], "-ofm")) {
178 model_id
= ARCHOS_ONDIO_FM
;
181 else if(!strcmp(argv
[1], "-osp")) {
186 model_id
= ARCHOS_ONDIO_SP
;
189 else if(!strcmp(argv
[1], "-neo")) {
195 else if(!strncmp(argv
[1], "-mm=", 4)) {
200 version
= argv
[1][4];
204 printf("Multimedia needs an xor string\n");
208 else if(!strncmp(argv
[1], "-tcc=", 4)) {
213 if(!strcmp(&argv
[1][5], "sum"))
215 else if(!strcmp(&argv
[1][5], "crc"))
218 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
222 else if(!strncmp(argv
[1], "-add=", 5)) {
227 if(!strcmp(&argv
[1][5], "h120"))
229 else if(!strcmp(&argv
[1][5], "h140"))
230 modelnum
= 0; /* the same as the h120 */
231 else if(!strcmp(&argv
[1][5], "h100"))
233 else if(!strcmp(&argv
[1][5], "h300"))
235 else if(!strcmp(&argv
[1][5], "ipco"))
237 else if(!strcmp(&argv
[1][5], "nano"))
239 else if(!strcmp(&argv
[1][5], "ipvd"))
241 else if(!strcmp(&argv
[1][5], "fp7x"))
243 else if(!strcmp(&argv
[1][5], "ip3g"))
245 else if(!strcmp(&argv
[1][5], "ip4g"))
247 else if(!strcmp(&argv
[1][5], "mini"))
249 else if(!strcmp(&argv
[1][5], "iax5"))
251 else if(!strcmp(&argv
[1][5], "mn2g"))
253 else if(!strcmp(&argv
[1][5], "h10"))
255 else if(!strcmp(&argv
[1][5], "h10_5gb"))
257 else if(!strcmp(&argv
[1][5], "tpj2"))
259 else if(!strcmp(&argv
[1][5], "e200"))
261 else if(!strcmp(&argv
[1][5], "iam5"))
263 else if(!strcmp(&argv
[1][5], "giga"))
265 else if(!strcmp(&argv
[1][5], "1g2g"))
267 else if(!strcmp(&argv
[1][5], "c200"))
269 else if(!strcmp(&argv
[1][5], "gigs"))
271 else if(!strcmp(&argv
[1][5], "m500"))
273 else if(!strcmp(&argv
[1][5], "m100"))
275 else if(!strcmp(&argv
[1][5], "d2"))
277 else if(!strcmp(&argv
[1][5], "iam3"))
279 else if (!strcmp(&argv
[1][5], "m200"))
281 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
283 else if (!strcmp(&argv
[1][5], "i7"))
285 else if (!strcmp(&argv
[1][5], "ldax"))
287 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
289 else if (!strcmp(&argv
[1][5], "clip"))
291 else if (!strcmp(&argv
[1][5], "e2v2"))
293 else if (!strcmp(&argv
[1][5], "m2v4"))
295 else if (!strcmp(&argv
[1][5], "fuze"))
297 else if (!strcmp(&argv
[1][5], "c2v2"))
299 else if (!strcmp(&argv
[1][5], "x747"))
301 else if (!strcmp(&argv
[1][5], "y820")) /* Samsung YH-820 */
303 else if (!strcmp(&argv
[1][5], "y920")) /* Samsung YH-920 */
305 else if (!strcmp(&argv
[1][5], "y925")) /* Samsung YH-925 */
307 else if (!strcmp(&argv
[1][5], "clv2")) /* Sansa Clipv2 */
310 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
313 /* we store a 4-letter model name too, for humans */
314 strcpy(modelname
, &argv
[1][5]);
315 chksum
= modelnum
; /* start checksum calcs with this */
318 else if(!strcmp(argv
[1], "-iriver")) {
319 /* iRiver code dealt with in the iriver.c code */
322 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
324 else if(!strcmp(argv
[1], "-gigabeat")) {
325 /* iRiver code dealt with in the iriver.c code */
328 gigabeat_code(iname
, oname
);
331 else if(!strcmp(argv
[1], "-gigabeats")) {
334 return gigabeat_s_code(iname
, oname
);
336 else if(!strcmp(argv
[1], "-iaudiox5")) {
339 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
341 else if(!strcmp(argv
[1], "-iaudiox5v")) {
344 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
346 else if(!strcmp(argv
[1], "-iaudiom5")) {
349 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
351 else if(!strcmp(argv
[1], "-iaudiom3")) {
354 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
356 else if(!strcmp(argv
[1], "-ipod3g")) {
359 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
361 else if(!strcmp(argv
[1], "-ipod4g")) {
364 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
366 else if(!strcmp(argv
[1], "-ipod5g")) {
369 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
371 else if(!strncmp(argv
[1], "-creative=", 10))
373 if(!strcmp(argv
[2], "-no-ciff"))
375 creative_enable_ciff
= false;
381 creative_enable_ciff
= true;
385 if(!strcmp(&argv
[1][10], "zvm"))
386 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
387 else if(!strcmp(&argv
[1][10], "zvm60"))
388 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
389 else if(!strcmp(&argv
[1][10], "zenvision"))
390 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
391 else if(!strcmp(&argv
[1][10], "zenv"))
392 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
393 else if(!strcmp(&argv
[1][10], "zen"))
394 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
397 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
401 else if(!strncmp(argv
[1], "-mi4", 4)) {
406 if(!strcmp(&argv
[1][4], "v2")) {
407 mi4magic
= MI4_MAGIC_DEFAULT
;
408 version
= 0x00010201;
410 else if(!strcmp(&argv
[1][4], "v3")) {
411 mi4magic
= MI4_MAGIC_DEFAULT
;
412 version
= 0x00010301;
414 else if(!strcmp(&argv
[1][4], "r")) {
415 mi4magic
= MI4_MAGIC_R
;
416 version
= 0x00010301;
419 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
426 if(!strncmp(argv
[2], "-model=", 7)) {
429 strncpy(model
, &argv
[2][7], 4);
431 if(!strncmp(argv
[3], "-type=", 6)) {
434 strncpy(type
, &argv
[3][6], 4);
438 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
442 file
= fopen(iname
,"rb");
447 fseek(file
,0,SEEK_END
);
448 length
= ftell(file
);
449 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
451 if ((method
== scramble
) &&
452 ((length
+ headerlen
) >= size_limit
[model_id
])) {
453 printf("error: firmware image is %ld bytes while max size is %u!\n",
455 size_limit
[model_id
]);
460 fseek(file
,0,SEEK_SET
);
461 inbuf
= malloc(length
);
463 outbuf
= malloc(length
*2);
464 else if(method
== add
)
465 outbuf
= malloc(length
+ 8);
467 outbuf
= malloc(length
);
468 if ( !inbuf
|| !outbuf
) {
469 printf("out of memory!\n");
473 /* zero-fill the last 4 bytes to make sure there's no rubbish there
474 when we write the size-aligned file later */
475 memset(outbuf
+length
-4, 0, 4);
479 i
=fread(inbuf
,1,length
,file
);
489 for (i
= 0; i
< length
; i
++) {
490 /* add 8 unsigned bits but keep a 32 bit sum */
496 for (i
= 0; i
< length
; i
++) {
497 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
498 unsigned char data
= inbuf
[i
];
499 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
507 for (i
=0; i
<length
; i
++) {
509 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
510 outbuf
[slen
++] = inbuf
[i
];
515 /* dummy case just to silence picky compilers */
519 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
520 /* calculate checksum */
521 for (i
=0;i
<length
;i
++)
525 memset(header
, 0, sizeof header
);
530 int2be(chksum
, header
); /* checksum, big-endian */
531 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
532 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
538 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
539 telechips_encode_sum(outbuf
, length
);
543 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
544 telechips_encode_crc(outbuf
, length
);
548 if (headerlen
== 6) {
549 int2be(length
, header
);
550 header
[4] = (crc
>> 8) & 0xff;
551 header
[5] = crc
& 0xff;
557 header
[3] = 0xff; /* ??? */
559 header
[6] = (crc
>> 8) & 0xff;
560 header
[7] = crc
& 0xff;
562 header
[11] = version
;
564 header
[15] = headerlen
; /* really? */
566 int2be(length
, &header
[20]);
572 int xorlen
= strlen(xorstring
);
575 for (i
=0; i
<slen
; i
++)
576 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
578 /* calculate checksum */
579 for (i
=0; i
<slen
; i
++)
582 header
[0] = header
[2] = 'Z';
583 header
[1] = header
[3] = version
;
584 int2le(length
, &header
[4]);
585 int2le(slen
, &header
[8]);
586 int2le(crc
, &header
[12]);
591 #define MY_FIRMWARE_TYPE "Rockbox"
592 #define MY_HEADER_VERSION 1
594 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
595 header
[9]='\0'; /*shouldn't have to, but to be SURE */
596 header
[10]=MY_HEADER_VERSION
&0xFF;
597 header
[11]=(crc
>>8)&0xFF;
599 int2be(sizeof(header
), &header
[12]);
604 file
= fopen(oname
,"wb");
610 if ( !fwrite(header
,headerlen
,1,file
) ) {
615 if ( !fwrite(outbuf
,length
,1,file
) ) {
627 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
632 unsigned char *outbuf
;
634 unsigned char sum
= 0;
636 file
= fopen(iname
, "rb");
641 fseek(file
,0,SEEK_END
);
642 length
= ftell(file
);
644 fseek(file
,0,SEEK_SET
);
645 outbuf
= malloc(length
+0x1030);
648 printf("out of memory!\n");
652 len
= fread(outbuf
+0x1030, 1, length
, file
);
653 if(len
< (size_t) length
) {
658 memset(outbuf
, 0, 0x1030);
659 strcpy((char *)outbuf
, idstring
);
660 memcpy(outbuf
+0x20, iaudio_bl_flash
,
661 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
662 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
663 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
666 for(i
= 0; i
< length
;i
++)
667 sum
+= outbuf
[0x1030 + i
];
669 int2be(length
, &outbuf
[0x1024]);
670 outbuf
[0x102b] = sum
;
674 file
= fopen(oname
, "wb");
680 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
681 if(len
< (size_t)length
) {
691 /* Create an ipod firmware partition image
693 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
695 This function doesn't yet handle the Broadcom resource image for the 5g,
696 so the resulting images won't be usable.
698 This has also only been tested on an ipod Photo
701 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
703 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
724 unsigned int sum
= 0;
725 unsigned int rsrcsum
= 0;
726 unsigned char *outbuf
;
730 file
= fopen(iname
, "rb");
735 fseek(file
,0,SEEK_END
);
736 length
= ftell(file
);
738 fseek(file
,0,SEEK_SET
);
740 bufsize
=(length
+0x4600);
742 bufsize
= (bufsize
+ 0x400) & ~0x200;
745 outbuf
= malloc(bufsize
);
748 printf("out of memory!\n");
752 len
= fread(outbuf
+0x4600, 1, length
, file
);
753 if(len
< (size_t)length
) {
759 /* Calculate checksum for later use in header */
760 for(i
= 0x4600; i
< 0x4600+length
;i
++)
763 /* Clear the header area to zero */
764 memset(outbuf
, 0, 0x4600);
766 /* APPLE STOP SIGN */
767 strcpy((char *)outbuf
, apple_stop_sign
);
770 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
771 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
772 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
773 short2le(fw_ver
, &outbuf
[0x10a]);
775 /* Firmware Directory - "osos" entry */
776 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
777 int2le(0, &outbuf
[0x4208]); /* id */
778 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
779 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
780 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
781 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
782 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
783 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
784 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
786 /* "rsrc" entry (if applicable) */
788 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
792 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
793 int2le(0, &outbuf
[0x4230]); /* id */
794 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
795 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
796 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
797 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
798 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
799 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
800 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
803 file
= fopen(oname
, "wb");
809 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
810 if(len
< (size_t)length
) {