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
);
36 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, ldax, m200, c100, clip, e2v2, m2v4,\n"
127 "\t fuze, c2v2, clv2, y820, y920, y925, x747, 747p, \n"
129 printf("\nNo option results in Archos standard player/recorder format.\n");
134 int main (int argc
, char** argv
)
136 unsigned long length
,i
,slen
=0;
137 unsigned char *inbuf
,*outbuf
;
138 unsigned short crc
=0;
139 unsigned long chksum
=0; /* 32 bit checksum */
140 unsigned char header
[24];
141 char *iname
= argv
[1];
142 char *oname
= argv
[2];
143 char *xorstring
=NULL
;
147 unsigned long modelnum
;
150 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
151 bool creative_enable_ciff
;
153 model_id
= ARCHOS_PLAYER
;
159 if(!strcmp(argv
[1], "-fm")) {
164 model_id
= ARCHOS_FMRECORDER
;
167 else if(!strcmp(argv
[1], "-v2")) {
172 model_id
= ARCHOS_V2RECORDER
;
175 else if(!strcmp(argv
[1], "-ofm")) {
180 model_id
= ARCHOS_ONDIO_FM
;
183 else if(!strcmp(argv
[1], "-osp")) {
188 model_id
= ARCHOS_ONDIO_SP
;
191 else if(!strcmp(argv
[1], "-neo")) {
197 else if(!strncmp(argv
[1], "-mm=", 4)) {
202 version
= argv
[1][4];
206 printf("Multimedia needs an xor string\n");
210 else if(!strncmp(argv
[1], "-tcc=", 4)) {
215 if(!strcmp(&argv
[1][5], "sum"))
217 else if(!strcmp(&argv
[1][5], "crc"))
220 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
224 else if(!strncmp(argv
[1], "-add=", 5)) {
229 if(!strcmp(&argv
[1][5], "h120"))
231 else if(!strcmp(&argv
[1][5], "h140"))
232 modelnum
= 0; /* the same as the h120 */
233 else if(!strcmp(&argv
[1][5], "h100"))
235 else if(!strcmp(&argv
[1][5], "h300"))
237 else if(!strcmp(&argv
[1][5], "ipco"))
239 else if(!strcmp(&argv
[1][5], "nano"))
241 else if(!strcmp(&argv
[1][5], "ipvd"))
243 else if(!strcmp(&argv
[1][5], "fp7x"))
245 else if(!strcmp(&argv
[1][5], "ip3g"))
247 else if(!strcmp(&argv
[1][5], "ip4g"))
249 else if(!strcmp(&argv
[1][5], "mini"))
251 else if(!strcmp(&argv
[1][5], "iax5"))
253 else if(!strcmp(&argv
[1][5], "mn2g"))
255 else if(!strcmp(&argv
[1][5], "h10"))
257 else if(!strcmp(&argv
[1][5], "h10_5gb"))
259 else if(!strcmp(&argv
[1][5], "tpj2"))
261 else if(!strcmp(&argv
[1][5], "e200"))
263 else if(!strcmp(&argv
[1][5], "iam5"))
265 else if(!strcmp(&argv
[1][5], "giga"))
267 else if(!strcmp(&argv
[1][5], "1g2g"))
269 else if(!strcmp(&argv
[1][5], "c200"))
271 else if(!strcmp(&argv
[1][5], "gigs"))
273 else if(!strcmp(&argv
[1][5], "m500"))
275 else if(!strcmp(&argv
[1][5], "m100"))
277 else if(!strcmp(&argv
[1][5], "d2"))
279 else if(!strcmp(&argv
[1][5], "iam3"))
281 else if (!strcmp(&argv
[1][5], "m200"))
283 else if(!strcmp(&argv
[1][5], "c100"))
285 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
287 else if (!strcmp(&argv
[1][5], "i7"))
289 else if (!strcmp(&argv
[1][5], "ldax"))
291 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
293 else if (!strcmp(&argv
[1][5], "clip"))
295 else if (!strcmp(&argv
[1][5], "e2v2"))
297 else if (!strcmp(&argv
[1][5], "m2v4"))
299 else if (!strcmp(&argv
[1][5], "fuze"))
301 else if (!strcmp(&argv
[1][5], "c2v2"))
303 else if (!strcmp(&argv
[1][5], "x747"))
305 else if (!strcmp(&argv
[1][5], "747p"))
307 else if (!strcmp(&argv
[1][5], "y820")) /* Samsung YH-820 */
309 else if (!strcmp(&argv
[1][5], "y920")) /* Samsung YH-920 */
311 else if (!strcmp(&argv
[1][5], "y925")) /* Samsung YH-925 */
313 else if (!strcmp(&argv
[1][5], "clv2")) /* Sansa Clipv2 */
315 else if (!strcmp(&argv
[1][5], "x777"))
317 else if (!strcmp(&argv
[1][5], "nn2g")) /* iPod Nano 2nd Gen */
319 else if (!strcmp(&argv
[1][5], "x767"))
322 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
325 /* we store a 4-letter model name too, for humans */
326 strcpy(modelname
, &argv
[1][5]);
327 chksum
= modelnum
; /* start checksum calcs with this */
330 else if(!strcmp(argv
[1], "-iriver")) {
331 /* iRiver code dealt with in the iriver.c code */
334 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
336 else if(!strcmp(argv
[1], "-gigabeat")) {
337 /* iRiver code dealt with in the iriver.c code */
340 gigabeat_code(iname
, oname
);
343 else if(!strcmp(argv
[1], "-gigabeats")) {
346 return gigabeat_s_code(iname
, oname
);
348 else if(!strcmp(argv
[1], "-iaudiox5")) {
351 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
353 else if(!strcmp(argv
[1], "-iaudiox5v")) {
356 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
358 else if(!strcmp(argv
[1], "-iaudiom5")) {
361 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
363 else if(!strcmp(argv
[1], "-iaudiom3")) {
366 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
368 else if(!strcmp(argv
[1], "-ipod3g")) {
371 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
373 else if(!strcmp(argv
[1], "-ipod4g")) {
376 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
378 else if(!strcmp(argv
[1], "-ipod5g")) {
381 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
383 else if(!strncmp(argv
[1], "-creative=", 10)) {
384 if(!strcmp(argv
[2], "-no-ciff"))
386 creative_enable_ciff
= false;
392 creative_enable_ciff
= true;
396 if(!strcmp(&argv
[1][10], "zvm"))
397 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
398 else if(!strcmp(&argv
[1][10], "zvm60"))
399 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
400 else if(!strcmp(&argv
[1][10], "zenvision"))
401 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
402 else if(!strcmp(&argv
[1][10], "zenv"))
403 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
404 else if(!strcmp(&argv
[1][10], "zen"))
405 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
408 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
412 else if(!strcmp(argv
[1], "-ccpmp")) {
415 return ccpmp_encode(iname
, oname
);
417 else if(!strncmp(argv
[1], "-mi4", 4)) {
422 if(!strcmp(&argv
[1][4], "v2")) {
423 mi4magic
= MI4_MAGIC_DEFAULT
;
424 version
= 0x00010201;
426 else if(!strcmp(&argv
[1][4], "v3")) {
427 mi4magic
= MI4_MAGIC_DEFAULT
;
428 version
= 0x00010301;
430 else if(!strcmp(&argv
[1][4], "r")) {
431 mi4magic
= MI4_MAGIC_R
;
432 version
= 0x00010301;
435 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
442 if(!strncmp(argv
[2], "-model=", 7)) {
445 strncpy(model
, &argv
[2][7], 4);
447 if(!strncmp(argv
[3], "-type=", 6)) {
450 strncpy(type
, &argv
[3][6], 4);
454 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
458 file
= fopen(iname
,"rb");
463 fseek(file
,0,SEEK_END
);
464 length
= ftell(file
);
465 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
467 if ((method
== scramble
) &&
468 ((length
+ headerlen
) >= size_limit
[model_id
])) {
469 printf("error: firmware image is %ld bytes while max size is %u!\n",
471 size_limit
[model_id
]);
476 fseek(file
,0,SEEK_SET
);
477 inbuf
= malloc(length
);
479 outbuf
= malloc(length
*2);
480 else if(method
== add
)
481 outbuf
= malloc(length
+ 8);
483 outbuf
= malloc(length
);
484 if ( !inbuf
|| !outbuf
) {
485 printf("out of memory!\n");
489 /* zero-fill the last 4 bytes to make sure there's no rubbish there
490 when we write the size-aligned file later */
491 memset(outbuf
+length
-4, 0, 4);
495 i
=fread(inbuf
,1,length
,file
);
505 for (i
= 0; i
< length
; i
++) {
506 /* add 8 unsigned bits but keep a 32 bit sum */
512 for (i
= 0; i
< length
; i
++) {
513 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
514 unsigned char data
= inbuf
[i
];
515 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
523 for (i
=0; i
<length
; i
++) {
525 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
526 outbuf
[slen
++] = inbuf
[i
];
531 /* dummy case just to silence picky compilers */
535 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
536 /* calculate checksum */
537 for (i
=0;i
<length
;i
++)
541 memset(header
, 0, sizeof header
);
546 int2be(chksum
, header
); /* checksum, big-endian */
547 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
548 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
554 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
555 telechips_encode_sum(outbuf
, length
);
559 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
560 telechips_encode_crc(outbuf
, length
);
564 if (headerlen
== 6) {
565 int2be(length
, header
);
566 header
[4] = (crc
>> 8) & 0xff;
567 header
[5] = crc
& 0xff;
573 header
[3] = 0xff; /* ??? */
575 header
[6] = (crc
>> 8) & 0xff;
576 header
[7] = crc
& 0xff;
578 header
[11] = version
;
580 header
[15] = headerlen
; /* really? */
582 int2be(length
, &header
[20]);
588 int xorlen
= strlen(xorstring
);
591 for (i
=0; i
<slen
; i
++)
592 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
594 /* calculate checksum */
595 for (i
=0; i
<slen
; i
++)
598 header
[0] = header
[2] = 'Z';
599 header
[1] = header
[3] = version
;
600 int2le(length
, &header
[4]);
601 int2le(slen
, &header
[8]);
602 int2le(crc
, &header
[12]);
607 #define MY_FIRMWARE_TYPE "Rockbox"
608 #define MY_HEADER_VERSION 1
610 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
611 header
[9]='\0'; /*shouldn't have to, but to be SURE */
612 header
[10]=MY_HEADER_VERSION
&0xFF;
613 header
[11]=(crc
>>8)&0xFF;
615 int2be(sizeof(header
), &header
[12]);
620 file
= fopen(oname
,"wb");
626 if ( !fwrite(header
,headerlen
,1,file
) ) {
631 if ( !fwrite(outbuf
,length
,1,file
) ) {
643 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
648 unsigned char *outbuf
;
650 unsigned char sum
= 0;
652 file
= fopen(iname
, "rb");
657 fseek(file
,0,SEEK_END
);
658 length
= ftell(file
);
660 fseek(file
,0,SEEK_SET
);
661 outbuf
= malloc(length
+0x1030);
664 printf("out of memory!\n");
668 len
= fread(outbuf
+0x1030, 1, length
, file
);
669 if(len
< (size_t) length
) {
674 memset(outbuf
, 0, 0x1030);
675 strcpy((char *)outbuf
, idstring
);
676 memcpy(outbuf
+0x20, iaudio_bl_flash
,
677 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
678 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
679 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
682 for(i
= 0; i
< length
;i
++)
683 sum
+= outbuf
[0x1030 + i
];
685 int2be(length
, &outbuf
[0x1024]);
686 outbuf
[0x102b] = sum
;
690 file
= fopen(oname
, "wb");
696 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
697 if(len
< (size_t)length
) {
707 /* Create an ipod firmware partition image
709 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
711 This function doesn't yet handle the Broadcom resource image for the 5g,
712 so the resulting images won't be usable.
714 This has also only been tested on an ipod Photo
717 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
719 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
740 unsigned int sum
= 0;
741 unsigned int rsrcsum
= 0;
742 unsigned char *outbuf
;
746 file
= fopen(iname
, "rb");
751 fseek(file
,0,SEEK_END
);
752 length
= ftell(file
);
754 fseek(file
,0,SEEK_SET
);
756 bufsize
=(length
+0x4600);
758 bufsize
= (bufsize
+ 0x400) & ~0x200;
761 outbuf
= malloc(bufsize
);
764 printf("out of memory!\n");
768 len
= fread(outbuf
+0x4600, 1, length
, file
);
769 if(len
< (size_t)length
) {
775 /* Calculate checksum for later use in header */
776 for(i
= 0x4600; i
< 0x4600+length
;i
++)
779 /* Clear the header area to zero */
780 memset(outbuf
, 0, 0x4600);
782 /* APPLE STOP SIGN */
783 strcpy((char *)outbuf
, apple_stop_sign
);
786 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
787 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
788 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
789 short2le(fw_ver
, &outbuf
[0x10a]);
791 /* Firmware Directory - "osos" entry */
792 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
793 int2le(0, &outbuf
[0x4208]); /* id */
794 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
795 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
796 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
797 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
798 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
799 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
800 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
802 /* "rsrc" entry (if applicable) */
804 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
808 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
809 int2le(0, &outbuf
[0x4230]); /* id */
810 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
811 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
812 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
813 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
814 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
815 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
816 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
819 file
= fopen(oname
, "wb");
825 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
826 if(len
< (size_t)length
) {
836 #define CCPMP_SIZE 0x500000
837 int ccpmp_encode(char *iname
, char *oname
)
842 unsigned char *outbuf
;
844 file
= fopen(iname
, "rb");
849 fseek(file
,0,SEEK_END
);
850 length
= ftell(file
);
852 fseek(file
,0,SEEK_SET
);
854 outbuf
= malloc(CCPMP_SIZE
);
857 printf("out of memory!\n");
861 len
= fread(outbuf
, 1, length
, file
);
862 if(len
< (size_t)length
) {
868 /* Clear the tail area to 0xFF */
869 memset(&outbuf
[length
], 0xFF, CCPMP_SIZE
- length
);
872 int2le(length
, &outbuf
[0x4]);
874 file
= fopen(oname
, "wb");
880 len
= fwrite(outbuf
, 1, CCPMP_SIZE
, file
);
881 if(len
< (size_t)length
) {