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 printf("\nNo option results in Archos standard player/recorder format.\n");
131 int main (int argc
, char** argv
)
133 unsigned long length
,i
,slen
=0;
134 unsigned char *inbuf
,*outbuf
;
135 unsigned short crc
=0;
136 unsigned long chksum
=0; /* 32 bit checksum */
137 unsigned char header
[24];
138 char *iname
= argv
[1];
139 char *oname
= argv
[2];
140 char *xorstring
=NULL
;
144 unsigned long modelnum
;
147 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
148 bool creative_enable_ciff
;
150 model_id
= ARCHOS_PLAYER
;
156 if(!strcmp(argv
[1], "-fm")) {
161 model_id
= ARCHOS_FMRECORDER
;
164 else if(!strcmp(argv
[1], "-v2")) {
169 model_id
= ARCHOS_V2RECORDER
;
172 else if(!strcmp(argv
[1], "-ofm")) {
177 model_id
= ARCHOS_ONDIO_FM
;
180 else if(!strcmp(argv
[1], "-osp")) {
185 model_id
= ARCHOS_ONDIO_SP
;
188 else if(!strcmp(argv
[1], "-neo")) {
194 else if(!strncmp(argv
[1], "-mm=", 4)) {
199 version
= argv
[1][4];
203 printf("Multimedia needs an xor string\n");
207 else if(!strncmp(argv
[1], "-tcc=", 4)) {
212 if(!strcmp(&argv
[1][5], "sum"))
214 else if(!strcmp(&argv
[1][5], "crc"))
217 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
221 else if(!strncmp(argv
[1], "-add=", 5)) {
226 if(!strcmp(&argv
[1][5], "h120"))
228 else if(!strcmp(&argv
[1][5], "h140"))
229 modelnum
= 0; /* the same as the h120 */
230 else if(!strcmp(&argv
[1][5], "h100"))
232 else if(!strcmp(&argv
[1][5], "h300"))
234 else if(!strcmp(&argv
[1][5], "ipco"))
236 else if(!strcmp(&argv
[1][5], "nano"))
238 else if(!strcmp(&argv
[1][5], "ipvd"))
240 else if(!strcmp(&argv
[1][5], "fp7x"))
242 else if(!strcmp(&argv
[1][5], "ip3g"))
244 else if(!strcmp(&argv
[1][5], "ip4g"))
246 else if(!strcmp(&argv
[1][5], "mini"))
248 else if(!strcmp(&argv
[1][5], "iax5"))
250 else if(!strcmp(&argv
[1][5], "mn2g"))
252 else if(!strcmp(&argv
[1][5], "h10"))
254 else if(!strcmp(&argv
[1][5], "h10_5gb"))
256 else if(!strcmp(&argv
[1][5], "tpj2"))
258 else if(!strcmp(&argv
[1][5], "e200"))
260 else if(!strcmp(&argv
[1][5], "iam5"))
262 else if(!strcmp(&argv
[1][5], "giga"))
264 else if(!strcmp(&argv
[1][5], "1g2g"))
266 else if(!strcmp(&argv
[1][5], "c200"))
268 else if(!strcmp(&argv
[1][5], "gigs"))
270 else if(!strcmp(&argv
[1][5], "m500"))
272 else if(!strcmp(&argv
[1][5], "m100"))
274 else if(!strcmp(&argv
[1][5], "d2"))
276 else if(!strcmp(&argv
[1][5], "iam3"))
278 else if (!strcmp(&argv
[1][5], "m200"))
280 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
282 else if (!strcmp(&argv
[1][5], "i7"))
284 else if (!strcmp(&argv
[1][5], "ldax"))
286 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
288 else if (!strcmp(&argv
[1][5], "clip"))
290 else if (!strcmp(&argv
[1][5], "e2v2"))
292 else if (!strcmp(&argv
[1][5], "m2v4"))
294 else if (!strcmp(&argv
[1][5], "fuze"))
296 else if (!strcmp(&argv
[1][5], "c2v2"))
298 else if (!strcmp(&argv
[1][5], "x747"))
301 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
304 /* we store a 4-letter model name too, for humans */
305 strcpy(modelname
, &argv
[1][5]);
306 chksum
= modelnum
; /* start checksum calcs with this */
309 else if(!strcmp(argv
[1], "-iriver")) {
310 /* iRiver code dealt with in the iriver.c code */
313 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
315 else if(!strcmp(argv
[1], "-gigabeat")) {
316 /* iRiver code dealt with in the iriver.c code */
319 gigabeat_code(iname
, oname
);
322 else if(!strcmp(argv
[1], "-gigabeats")) {
325 gigabeat_s_code(iname
, oname
);
328 else if(!strcmp(argv
[1], "-iaudiox5")) {
331 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
333 else if(!strcmp(argv
[1], "-iaudiox5v")) {
336 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
338 else if(!strcmp(argv
[1], "-iaudiom5")) {
341 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
343 else if(!strcmp(argv
[1], "-iaudiom3")) {
346 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
348 else if(!strcmp(argv
[1], "-ipod3g")) {
351 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
353 else if(!strcmp(argv
[1], "-ipod4g")) {
356 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
358 else if(!strcmp(argv
[1], "-ipod5g")) {
361 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
363 else if(!strncmp(argv
[1], "-creative=", 10))
365 if(!strcmp(argv
[2], "-no-ciff"))
367 creative_enable_ciff
= false;
373 creative_enable_ciff
= true;
377 if(!strcmp(&argv
[1][10], "zvm"))
378 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
379 else if(!strcmp(&argv
[1][10], "zvm60"))
380 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
381 else if(!strcmp(&argv
[1][10], "zenvision"))
382 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
383 else if(!strcmp(&argv
[1][10], "zenv"))
384 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
385 else if(!strcmp(&argv
[1][10], "zen"))
386 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
389 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
393 else if(!strncmp(argv
[1], "-mi4", 4)) {
398 if(!strcmp(&argv
[1][4], "v2")) {
399 mi4magic
= MI4_MAGIC_DEFAULT
;
400 version
= 0x00010201;
402 else if(!strcmp(&argv
[1][4], "v3")) {
403 mi4magic
= MI4_MAGIC_DEFAULT
;
404 version
= 0x00010301;
406 else if(!strcmp(&argv
[1][4], "r")) {
407 mi4magic
= MI4_MAGIC_R
;
408 version
= 0x00010301;
411 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
418 if(!strncmp(argv
[2], "-model=", 7)) {
421 strncpy(model
, &argv
[2][7], 4);
423 if(!strncmp(argv
[3], "-type=", 6)) {
426 strncpy(type
, &argv
[3][6], 4);
430 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
434 file
= fopen(iname
,"rb");
439 fseek(file
,0,SEEK_END
);
440 length
= ftell(file
);
441 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
443 if ((method
== scramble
) &&
444 ((length
+ headerlen
) >= size_limit
[model_id
])) {
445 printf("error: firmware image is %ld bytes while max size is %u!\n",
447 size_limit
[model_id
]);
452 fseek(file
,0,SEEK_SET
);
453 inbuf
= malloc(length
);
455 outbuf
= malloc(length
*2);
456 else if(method
== add
)
457 outbuf
= malloc(length
+ 8);
459 outbuf
= malloc(length
);
460 if ( !inbuf
|| !outbuf
) {
461 printf("out of memory!\n");
465 /* zero-fill the last 4 bytes to make sure there's no rubbish there
466 when we write the size-aligned file later */
467 memset(outbuf
+length
-4, 0, 4);
471 i
=fread(inbuf
,1,length
,file
);
481 for (i
= 0; i
< length
; i
++) {
482 /* add 8 unsigned bits but keep a 32 bit sum */
488 for (i
= 0; i
< length
; i
++) {
489 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
490 unsigned char data
= inbuf
[i
];
491 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
499 for (i
=0; i
<length
; i
++) {
501 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
502 outbuf
[slen
++] = inbuf
[i
];
507 /* dummy case just to silence picky compilers */
511 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
512 /* calculate checksum */
513 for (i
=0;i
<length
;i
++)
517 memset(header
, 0, sizeof header
);
522 int2be(chksum
, header
); /* checksum, big-endian */
523 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
524 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
530 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
531 telechips_encode_sum(outbuf
, length
);
535 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
536 telechips_encode_crc(outbuf
, length
);
540 if (headerlen
== 6) {
541 int2be(length
, header
);
542 header
[4] = (crc
>> 8) & 0xff;
543 header
[5] = crc
& 0xff;
549 header
[3] = 0xff; /* ??? */
551 header
[6] = (crc
>> 8) & 0xff;
552 header
[7] = crc
& 0xff;
554 header
[11] = version
;
556 header
[15] = headerlen
; /* really? */
558 int2be(length
, &header
[20]);
564 int xorlen
= strlen(xorstring
);
567 for (i
=0; i
<slen
; i
++)
568 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
570 /* calculate checksum */
571 for (i
=0; i
<slen
; i
++)
574 header
[0] = header
[2] = 'Z';
575 header
[1] = header
[3] = version
;
576 int2le(length
, &header
[4]);
577 int2le(slen
, &header
[8]);
578 int2le(crc
, &header
[12]);
583 #define MY_FIRMWARE_TYPE "Rockbox"
584 #define MY_HEADER_VERSION 1
586 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
587 header
[9]='\0'; /*shouldn't have to, but to be SURE */
588 header
[10]=MY_HEADER_VERSION
&0xFF;
589 header
[11]=(crc
>>8)&0xFF;
591 int2be(sizeof(header
), &header
[12]);
596 file
= fopen(oname
,"wb");
602 if ( !fwrite(header
,headerlen
,1,file
) ) {
607 if ( !fwrite(outbuf
,length
,1,file
) ) {
619 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
624 unsigned char *outbuf
;
626 unsigned char sum
= 0;
628 file
= fopen(iname
, "rb");
633 fseek(file
,0,SEEK_END
);
634 length
= ftell(file
);
636 fseek(file
,0,SEEK_SET
);
637 outbuf
= malloc(length
+0x1030);
640 printf("out of memory!\n");
644 len
= fread(outbuf
+0x1030, 1, length
, file
);
645 if(len
< (size_t) length
) {
650 memset(outbuf
, 0, 0x1030);
651 strcpy((char *)outbuf
, idstring
);
652 memcpy(outbuf
+0x20, iaudio_bl_flash
,
653 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
654 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
655 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
658 for(i
= 0; i
< length
;i
++)
659 sum
+= outbuf
[0x1030 + i
];
661 int2be(length
, &outbuf
[0x1024]);
662 outbuf
[0x102b] = sum
;
666 file
= fopen(oname
, "wb");
672 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
673 if(len
< (size_t)length
) {
683 /* Create an ipod firmware partition image
685 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
687 This function doesn't yet handle the Broadcom resource image for the 5g,
688 so the resulting images won't be usable.
690 This has also only been tested on an ipod Photo
693 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
695 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
716 unsigned int sum
= 0;
717 unsigned int rsrcsum
= 0;
718 unsigned char *outbuf
;
722 file
= fopen(iname
, "rb");
727 fseek(file
,0,SEEK_END
);
728 length
= ftell(file
);
730 fseek(file
,0,SEEK_SET
);
732 bufsize
=(length
+0x4600);
734 bufsize
= (bufsize
+ 0x400) & ~0x200;
737 outbuf
= malloc(bufsize
);
740 printf("out of memory!\n");
744 len
= fread(outbuf
+0x4600, 1, length
, file
);
745 if(len
< (size_t)length
) {
751 /* Calculate checksum for later use in header */
752 for(i
= 0x4600; i
< 0x4600+length
;i
++)
755 /* Clear the header area to zero */
756 memset(outbuf
, 0, 0x4600);
758 /* APPLE STOP SIGN */
759 strcpy((char *)outbuf
, apple_stop_sign
);
762 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
763 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
764 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
765 short2le(fw_ver
, &outbuf
[0x10a]);
767 /* Firmware Directory - "osos" entry */
768 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
769 int2le(0, &outbuf
[0x4208]); /* id */
770 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
771 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
772 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
773 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
774 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
775 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
776 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
778 /* "rsrc" entry (if applicable) */
780 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
784 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
785 int2le(0, &outbuf
[0x4230]); /* id */
786 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
787 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
788 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
789 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
790 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
791 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
792 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
795 file
= fopen(oname
, "wb");
801 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
802 if(len
< (size_t)length
) {