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, c100, clip, e2v2, m2v4,\n"
126 "\t fuze, 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], "c100"))
283 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
285 else if (!strcmp(&argv
[1][5], "i7"))
287 else if (!strcmp(&argv
[1][5], "ldax"))
289 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
291 else if (!strcmp(&argv
[1][5], "clip"))
293 else if (!strcmp(&argv
[1][5], "e2v2"))
295 else if (!strcmp(&argv
[1][5], "m2v4"))
297 else if (!strcmp(&argv
[1][5], "fuze"))
299 else if (!strcmp(&argv
[1][5], "c2v2"))
301 else if (!strcmp(&argv
[1][5], "x747"))
303 else if (!strcmp(&argv
[1][5], "y820")) /* Samsung YH-820 */
305 else if (!strcmp(&argv
[1][5], "y920")) /* Samsung YH-920 */
307 else if (!strcmp(&argv
[1][5], "y925")) /* Samsung YH-925 */
309 else if (!strcmp(&argv
[1][5], "clv2")) /* Sansa Clipv2 */
312 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
315 /* we store a 4-letter model name too, for humans */
316 strcpy(modelname
, &argv
[1][5]);
317 chksum
= modelnum
; /* start checksum calcs with this */
320 else if(!strcmp(argv
[1], "-iriver")) {
321 /* iRiver code dealt with in the iriver.c code */
324 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
326 else if(!strcmp(argv
[1], "-gigabeat")) {
327 /* iRiver code dealt with in the iriver.c code */
330 gigabeat_code(iname
, oname
);
333 else if(!strcmp(argv
[1], "-gigabeats")) {
336 return gigabeat_s_code(iname
, oname
);
338 else if(!strcmp(argv
[1], "-iaudiox5")) {
341 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
343 else if(!strcmp(argv
[1], "-iaudiox5v")) {
346 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
348 else if(!strcmp(argv
[1], "-iaudiom5")) {
351 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
353 else if(!strcmp(argv
[1], "-iaudiom3")) {
356 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
358 else if(!strcmp(argv
[1], "-ipod3g")) {
361 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
363 else if(!strcmp(argv
[1], "-ipod4g")) {
366 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
368 else if(!strcmp(argv
[1], "-ipod5g")) {
371 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
373 else if(!strncmp(argv
[1], "-creative=", 10))
375 if(!strcmp(argv
[2], "-no-ciff"))
377 creative_enable_ciff
= false;
383 creative_enable_ciff
= true;
387 if(!strcmp(&argv
[1][10], "zvm"))
388 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
389 else if(!strcmp(&argv
[1][10], "zvm60"))
390 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
391 else if(!strcmp(&argv
[1][10], "zenvision"))
392 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
393 else if(!strcmp(&argv
[1][10], "zenv"))
394 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
395 else if(!strcmp(&argv
[1][10], "zen"))
396 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
399 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
403 else if(!strncmp(argv
[1], "-mi4", 4)) {
408 if(!strcmp(&argv
[1][4], "v2")) {
409 mi4magic
= MI4_MAGIC_DEFAULT
;
410 version
= 0x00010201;
412 else if(!strcmp(&argv
[1][4], "v3")) {
413 mi4magic
= MI4_MAGIC_DEFAULT
;
414 version
= 0x00010301;
416 else if(!strcmp(&argv
[1][4], "r")) {
417 mi4magic
= MI4_MAGIC_R
;
418 version
= 0x00010301;
421 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
428 if(!strncmp(argv
[2], "-model=", 7)) {
431 strncpy(model
, &argv
[2][7], 4);
433 if(!strncmp(argv
[3], "-type=", 6)) {
436 strncpy(type
, &argv
[3][6], 4);
440 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
444 file
= fopen(iname
,"rb");
449 fseek(file
,0,SEEK_END
);
450 length
= ftell(file
);
451 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
453 if ((method
== scramble
) &&
454 ((length
+ headerlen
) >= size_limit
[model_id
])) {
455 printf("error: firmware image is %ld bytes while max size is %u!\n",
457 size_limit
[model_id
]);
462 fseek(file
,0,SEEK_SET
);
463 inbuf
= malloc(length
);
465 outbuf
= malloc(length
*2);
466 else if(method
== add
)
467 outbuf
= malloc(length
+ 8);
469 outbuf
= malloc(length
);
470 if ( !inbuf
|| !outbuf
) {
471 printf("out of memory!\n");
475 /* zero-fill the last 4 bytes to make sure there's no rubbish there
476 when we write the size-aligned file later */
477 memset(outbuf
+length
-4, 0, 4);
481 i
=fread(inbuf
,1,length
,file
);
491 for (i
= 0; i
< length
; i
++) {
492 /* add 8 unsigned bits but keep a 32 bit sum */
498 for (i
= 0; i
< length
; i
++) {
499 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
500 unsigned char data
= inbuf
[i
];
501 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
509 for (i
=0; i
<length
; i
++) {
511 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
512 outbuf
[slen
++] = inbuf
[i
];
517 /* dummy case just to silence picky compilers */
521 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
522 /* calculate checksum */
523 for (i
=0;i
<length
;i
++)
527 memset(header
, 0, sizeof header
);
532 int2be(chksum
, header
); /* checksum, big-endian */
533 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
534 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
540 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
541 telechips_encode_sum(outbuf
, length
);
545 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
546 telechips_encode_crc(outbuf
, length
);
550 if (headerlen
== 6) {
551 int2be(length
, header
);
552 header
[4] = (crc
>> 8) & 0xff;
553 header
[5] = crc
& 0xff;
559 header
[3] = 0xff; /* ??? */
561 header
[6] = (crc
>> 8) & 0xff;
562 header
[7] = crc
& 0xff;
564 header
[11] = version
;
566 header
[15] = headerlen
; /* really? */
568 int2be(length
, &header
[20]);
574 int xorlen
= strlen(xorstring
);
577 for (i
=0; i
<slen
; i
++)
578 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
580 /* calculate checksum */
581 for (i
=0; i
<slen
; i
++)
584 header
[0] = header
[2] = 'Z';
585 header
[1] = header
[3] = version
;
586 int2le(length
, &header
[4]);
587 int2le(slen
, &header
[8]);
588 int2le(crc
, &header
[12]);
593 #define MY_FIRMWARE_TYPE "Rockbox"
594 #define MY_HEADER_VERSION 1
596 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
597 header
[9]='\0'; /*shouldn't have to, but to be SURE */
598 header
[10]=MY_HEADER_VERSION
&0xFF;
599 header
[11]=(crc
>>8)&0xFF;
601 int2be(sizeof(header
), &header
[12]);
606 file
= fopen(oname
,"wb");
612 if ( !fwrite(header
,headerlen
,1,file
) ) {
617 if ( !fwrite(outbuf
,length
,1,file
) ) {
629 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
634 unsigned char *outbuf
;
636 unsigned char sum
= 0;
638 file
= fopen(iname
, "rb");
643 fseek(file
,0,SEEK_END
);
644 length
= ftell(file
);
646 fseek(file
,0,SEEK_SET
);
647 outbuf
= malloc(length
+0x1030);
650 printf("out of memory!\n");
654 len
= fread(outbuf
+0x1030, 1, length
, file
);
655 if(len
< (size_t) length
) {
660 memset(outbuf
, 0, 0x1030);
661 strcpy((char *)outbuf
, idstring
);
662 memcpy(outbuf
+0x20, iaudio_bl_flash
,
663 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
664 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
665 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
668 for(i
= 0; i
< length
;i
++)
669 sum
+= outbuf
[0x1030 + i
];
671 int2be(length
, &outbuf
[0x1024]);
672 outbuf
[0x102b] = sum
;
676 file
= fopen(oname
, "wb");
682 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
683 if(len
< (size_t)length
) {
693 /* Create an ipod firmware partition image
695 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
697 This function doesn't yet handle the Broadcom resource image for the 5g,
698 so the resulting images won't be usable.
700 This has also only been tested on an ipod Photo
703 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
705 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
726 unsigned int sum
= 0;
727 unsigned int rsrcsum
= 0;
728 unsigned char *outbuf
;
732 file
= fopen(iname
, "rb");
737 fseek(file
,0,SEEK_END
);
738 length
= ftell(file
);
740 fseek(file
,0,SEEK_SET
);
742 bufsize
=(length
+0x4600);
744 bufsize
= (bufsize
+ 0x400) & ~0x200;
747 outbuf
= malloc(bufsize
);
750 printf("out of memory!\n");
754 len
= fread(outbuf
+0x4600, 1, length
, file
);
755 if(len
< (size_t)length
) {
761 /* Calculate checksum for later use in header */
762 for(i
= 0x4600; i
< 0x4600+length
;i
++)
765 /* Clear the header area to zero */
766 memset(outbuf
, 0, 0x4600);
768 /* APPLE STOP SIGN */
769 strcpy((char *)outbuf
, apple_stop_sign
);
772 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
773 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
774 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
775 short2le(fw_ver
, &outbuf
[0x10a]);
777 /* Firmware Directory - "osos" entry */
778 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
779 int2le(0, &outbuf
[0x4208]); /* id */
780 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
781 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
782 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
783 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
784 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
785 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
786 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
788 /* "rsrc" entry (if applicable) */
790 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
794 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
795 int2le(0, &outbuf
[0x4230]); /* id */
796 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
797 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
798 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
799 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
800 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
801 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
802 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
805 file
= fopen(oname
, "wb");
811 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
812 if(len
< (size_t)length
) {