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, ldax, m200, c100, clip, e2v2, m2v4,\n"
127 "\t fuze, c2v2, clv2, y820, y920, y925, x747, 747p, \n"
128 "\t x777, nn2g, m244)\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"))
321 else if (!strcmp(&argv
[1][5], "m244"))
324 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
327 /* we store a 4-letter model name too, for humans */
328 strcpy(modelname
, &argv
[1][5]);
329 chksum
= modelnum
; /* start checksum calcs with this */
332 else if(!strcmp(argv
[1], "-iriver")) {
333 /* iRiver code dealt with in the iriver.c code */
336 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
338 else if(!strcmp(argv
[1], "-gigabeat")) {
339 /* iRiver code dealt with in the iriver.c code */
342 gigabeat_code(iname
, oname
);
345 else if(!strcmp(argv
[1], "-gigabeats")) {
348 return gigabeat_s_code(iname
, oname
);
350 else if(!strcmp(argv
[1], "-iaudiox5")) {
353 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
355 else if(!strcmp(argv
[1], "-iaudiox5v")) {
358 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
360 else if(!strcmp(argv
[1], "-iaudiom5")) {
363 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
365 else if(!strcmp(argv
[1], "-iaudiom3")) {
368 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
370 else if(!strcmp(argv
[1], "-ipod3g")) {
373 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
375 else if(!strcmp(argv
[1], "-ipod4g")) {
378 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
380 else if(!strcmp(argv
[1], "-ipod5g")) {
383 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
385 else if(!strncmp(argv
[1], "-creative=", 10)) {
386 if(!strcmp(argv
[2], "-no-ciff"))
388 creative_enable_ciff
= false;
394 creative_enable_ciff
= true;
398 if(!strcmp(&argv
[1][10], "zvm"))
399 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
400 else if(!strcmp(&argv
[1][10], "zvm60"))
401 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
402 else if(!strcmp(&argv
[1][10], "zenvision"))
403 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
404 else if(!strcmp(&argv
[1][10], "zenv"))
405 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
406 else if(!strcmp(&argv
[1][10], "zen"))
407 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
410 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
414 else if(!strcmp(argv
[1], "-ccpmp")) {
417 return ccpmp_encode(iname
, oname
);
419 else if(!strncmp(argv
[1], "-mi4", 4)) {
424 if(!strcmp(&argv
[1][4], "v2")) {
425 mi4magic
= MI4_MAGIC_DEFAULT
;
426 version
= 0x00010201;
428 else if(!strcmp(&argv
[1][4], "v3")) {
429 mi4magic
= MI4_MAGIC_DEFAULT
;
430 version
= 0x00010301;
432 else if(!strcmp(&argv
[1][4], "r")) {
433 mi4magic
= MI4_MAGIC_R
;
434 version
= 0x00010301;
437 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
444 if(!strncmp(argv
[2], "-model=", 7)) {
447 strncpy(model
, &argv
[2][7], 4);
449 if(!strncmp(argv
[3], "-type=", 6)) {
452 strncpy(type
, &argv
[3][6], 4);
456 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
460 file
= fopen(iname
,"rb");
465 fseek(file
,0,SEEK_END
);
466 length
= ftell(file
);
467 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
469 if ((method
== scramble
) &&
470 ((length
+ headerlen
) >= size_limit
[model_id
])) {
471 printf("error: firmware image is %ld bytes while max size is %u!\n",
473 size_limit
[model_id
]);
478 fseek(file
,0,SEEK_SET
);
479 inbuf
= malloc(length
);
481 outbuf
= malloc(length
*2);
482 else if(method
== add
)
483 outbuf
= malloc(length
+ 8);
485 outbuf
= malloc(length
);
486 if ( !inbuf
|| !outbuf
) {
487 printf("out of memory!\n");
491 /* zero-fill the last 4 bytes to make sure there's no rubbish there
492 when we write the size-aligned file later */
493 memset(outbuf
+length
-4, 0, 4);
497 i
=fread(inbuf
,1,length
,file
);
507 for (i
= 0; i
< length
; i
++) {
508 /* add 8 unsigned bits but keep a 32 bit sum */
514 for (i
= 0; i
< length
; i
++) {
515 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
516 unsigned char data
= inbuf
[i
];
517 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
525 for (i
=0; i
<length
; i
++) {
527 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
528 outbuf
[slen
++] = inbuf
[i
];
533 /* dummy case just to silence picky compilers */
537 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
538 /* calculate checksum */
539 for (i
=0;i
<length
;i
++)
543 memset(header
, 0, sizeof header
);
548 int2be(chksum
, header
); /* checksum, big-endian */
549 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
550 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
556 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
557 telechips_encode_sum(outbuf
, length
);
561 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
562 telechips_encode_crc(outbuf
, length
);
566 if (headerlen
== 6) {
567 int2be(length
, header
);
568 header
[4] = (crc
>> 8) & 0xff;
569 header
[5] = crc
& 0xff;
575 header
[3] = 0xff; /* ??? */
577 header
[6] = (crc
>> 8) & 0xff;
578 header
[7] = crc
& 0xff;
580 header
[11] = version
;
582 header
[15] = headerlen
; /* really? */
584 int2be(length
, &header
[20]);
590 int xorlen
= strlen(xorstring
);
593 for (i
=0; i
<slen
; i
++)
594 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
596 /* calculate checksum */
597 for (i
=0; i
<slen
; i
++)
600 header
[0] = header
[2] = 'Z';
601 header
[1] = header
[3] = version
;
602 int2le(length
, &header
[4]);
603 int2le(slen
, &header
[8]);
604 int2le(crc
, &header
[12]);
609 #define MY_FIRMWARE_TYPE "Rockbox"
610 #define MY_HEADER_VERSION 1
612 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
613 header
[9]='\0'; /*shouldn't have to, but to be SURE */
614 header
[10]=MY_HEADER_VERSION
&0xFF;
615 header
[11]=(crc
>>8)&0xFF;
617 int2be(sizeof(header
), &header
[12]);
622 file
= fopen(oname
,"wb");
628 if ( !fwrite(header
,headerlen
,1,file
) ) {
633 if ( !fwrite(outbuf
,length
,1,file
) ) {
645 static int iaudio_encode(char *iname
, char *oname
, char *idstring
)
650 unsigned char *outbuf
;
652 unsigned char sum
= 0;
654 file
= fopen(iname
, "rb");
659 fseek(file
,0,SEEK_END
);
660 length
= ftell(file
);
662 fseek(file
,0,SEEK_SET
);
663 outbuf
= malloc(length
+0x1030);
666 printf("out of memory!\n");
670 len
= fread(outbuf
+0x1030, 1, length
, file
);
671 if(len
< (size_t) length
) {
676 memset(outbuf
, 0, 0x1030);
677 strcpy((char *)outbuf
, idstring
);
678 memcpy(outbuf
+0x20, iaudio_bl_flash
,
679 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
680 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
681 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
684 for(i
= 0; i
< length
;i
++)
685 sum
+= outbuf
[0x1030 + i
];
687 int2be(length
, &outbuf
[0x1024]);
688 outbuf
[0x102b] = sum
;
692 file
= fopen(oname
, "wb");
698 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
699 if(len
< (size_t)length
) {
709 /* Create an ipod firmware partition image
711 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
713 This function doesn't yet handle the Broadcom resource image for the 5g,
714 so the resulting images won't be usable.
716 This has also only been tested on an ipod Photo
719 static int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
721 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
742 unsigned int sum
= 0;
743 unsigned int rsrcsum
= 0;
744 unsigned char *outbuf
;
748 file
= fopen(iname
, "rb");
753 fseek(file
,0,SEEK_END
);
754 length
= ftell(file
);
756 fseek(file
,0,SEEK_SET
);
758 bufsize
=(length
+0x4600);
760 bufsize
= (bufsize
+ 0x400) & ~0x200;
763 outbuf
= malloc(bufsize
);
766 printf("out of memory!\n");
770 len
= fread(outbuf
+0x4600, 1, length
, file
);
771 if(len
< (size_t)length
) {
777 /* Calculate checksum for later use in header */
778 for(i
= 0x4600; i
< 0x4600+length
;i
++)
781 /* Clear the header area to zero */
782 memset(outbuf
, 0, 0x4600);
784 /* APPLE STOP SIGN */
785 strcpy((char *)outbuf
, apple_stop_sign
);
788 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
789 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
790 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
791 short2le(fw_ver
, &outbuf
[0x10a]);
793 /* Firmware Directory - "osos" entry */
794 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
795 int2le(0, &outbuf
[0x4208]); /* id */
796 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
797 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
798 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
799 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
800 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
801 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
802 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
804 /* "rsrc" entry (if applicable) */
806 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
810 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
811 int2le(0, &outbuf
[0x4230]); /* id */
812 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
813 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
814 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
815 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
816 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
817 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
818 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
821 file
= fopen(oname
, "wb");
827 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
828 if(len
< (size_t)length
) {
838 #define CCPMP_SIZE 0x500000
839 static int ccpmp_encode(char *iname
, char *oname
)
844 unsigned char *outbuf
;
846 file
= fopen(iname
, "rb");
851 fseek(file
,0,SEEK_END
);
852 length
= ftell(file
);
854 fseek(file
,0,SEEK_SET
);
856 outbuf
= malloc(CCPMP_SIZE
);
859 printf("out of memory!\n");
863 len
= fread(outbuf
, 1, length
, file
);
864 if(len
< (size_t)length
) {
870 /* Clear the tail area to 0xFF */
871 memset(&outbuf
[length
], 0xFF, CCPMP_SIZE
- length
);
874 int2le(length
, &outbuf
[0x4]);
876 file
= fopen(oname
, "wb");
882 len
= fwrite(outbuf
, 1, CCPMP_SIZE
, file
);
883 if(len
< (size_t)length
) {