1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 - 2007 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
26 #include "gigabeats.h"
28 #include "telechips.h"
30 #include "iaudio_bl_flash.h"
32 int iaudio_encode(char *iname
, char *oname
, char *idstring
);
33 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
);
37 ARCHOS_PLAYER
, /* and V1 recorder */
44 static unsigned int size_limit
[] =
46 0x32000, /* ARCHOS_PLAYER */
47 0x64000, /* ARCHOS_V2RECORDER */
48 0x64000, /* ARCHOS_FMRECORDER */
49 0x64000, /* ARCHOS_ONDIO_SP */
50 0x64000 /* ARCHOS_ONDIO_FM */
53 void short2le(unsigned short val
, unsigned char* addr
)
56 addr
[1] = (val
>> 8) & 0xff;
59 unsigned int le2int(unsigned char* buf
)
61 unsigned int res
= (buf
[3] << 24) | (buf
[2] << 16) | (buf
[1] << 8) | buf
[0];
66 void int2le(unsigned int val
, unsigned char* addr
)
69 addr
[1] = (val
>> 8) & 0xff;
70 addr
[2] = (val
>> 16) & 0xff;
71 addr
[3] = (val
>> 24) & 0xff;
74 void int2be(unsigned int val
, unsigned char* addr
)
76 addr
[0] = (val
>> 24) & 0xff;
77 addr
[1] = (val
>> 16) & 0xff;
78 addr
[2] = (val
>> 8) & 0xff;
82 void short2be(unsigned short val
, unsigned char* addr
)
84 addr
[0] = (val
>> 8) & 0xff;
90 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
92 "\t-fm Archos FM recorder format\n"
93 "\t-v2 Archos V2 recorder format\n"
94 "\t-ofm Archos Ondio FM recorder format\n"
95 "\t-osp Archos Ondio SP format\n"
96 "\t-neo SSI Neo format\n"
97 "\t-mm=X Archos Multimedia format (X values: A=JBMM, B=AV1xx, C=AV3xx)\n"
98 "\t-iriver iRiver format\n"
99 "\t-iaudiox5 iAudio X5 format\n"
100 "\t-iaudiox5v iAudio X5V format\n"
101 "\t-iaudiom5 iAudio M5 format\n"
102 "\t-iaudiom3 iAudio M3 format\n");
103 printf("\t-ipod3g ipod firmware partition format (3rd Gen)\n"
104 "\t-ipod4g ipod firmware partition format (4th Gen, Mini, Nano, Photo/Color)\n"
105 "\t-ipod5g ipod firmware partition format (5th Gen - aka Video)\n"
106 "\t-creative=X Creative firmware structure format\n"
107 "\t-gigabeat Toshiba Gigabeat F/X format\n"
108 "\t-gigabeats Toshiba Gigabeat S format\n"
109 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
110 "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
111 "\t-mi4r Sandisk Rhapsody .mi4 format\n"
112 "\t All mi4 options take two optional arguments:\n");
113 printf("\t -model=XXXX where XXXX is the model id string\n"
114 "\t -type=XXXX where XXXX is a string indicating the \n"
115 "\t type of binary, eg. RBOS, RBBL\n"
116 "\t-tcc=X Telechips generic firmware format (X values: sum, crc)\n"
117 "\t-add=X Rockbox generic \"add-up\" checksum format\n"
118 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd, mn2g\n"
119 "\t ip3g, ip4g, mini, iax5, iam5, iam3, h10, h10_5gb,\n"
120 "\t tpj2, c200, e200, giga, gigs, m100, m500, d2, zvm)\n");
121 printf("\nNo option results in Archos standard player/recorder format.\n");
126 int main (int argc
, char** argv
)
128 unsigned long length
,i
,slen
=0;
129 unsigned char *inbuf
,*outbuf
;
130 unsigned short crc
=0;
131 unsigned long chksum
=0; /* 32 bit checksum */
132 unsigned char header
[24];
133 char *iname
= argv
[1];
134 char *oname
= argv
[2];
135 char *xorstring
=NULL
;
139 unsigned long modelnum
;
142 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
144 model_id
= ARCHOS_PLAYER
;
150 if(!strcmp(argv
[1], "-fm")) {
155 model_id
= ARCHOS_FMRECORDER
;
158 else if(!strcmp(argv
[1], "-v2")) {
163 model_id
= ARCHOS_V2RECORDER
;
166 else if(!strcmp(argv
[1], "-ofm")) {
171 model_id
= ARCHOS_ONDIO_FM
;
174 else if(!strcmp(argv
[1], "-osp")) {
179 model_id
= ARCHOS_ONDIO_SP
;
182 else if(!strcmp(argv
[1], "-neo")) {
188 else if(!strncmp(argv
[1], "-mm=", 4)) {
193 version
= argv
[1][4];
197 printf("Multimedia needs an xor string\n");
201 else if(!strncmp(argv
[1], "-tcc=", 4)) {
206 if(!strcmp(&argv
[1][5], "sum"))
208 else if(!strcmp(&argv
[1][5], "crc"))
211 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
215 else if(!strncmp(argv
[1], "-add=", 5)) {
220 if(!strcmp(&argv
[1][5], "h120"))
222 else if(!strcmp(&argv
[1][5], "h140"))
223 modelnum
= 0; /* the same as the h120 */
224 else if(!strcmp(&argv
[1][5], "h100"))
226 else if(!strcmp(&argv
[1][5], "h300"))
228 else if(!strcmp(&argv
[1][5], "ipco"))
230 else if(!strcmp(&argv
[1][5], "nano"))
232 else if(!strcmp(&argv
[1][5], "ipvd"))
234 else if(!strcmp(&argv
[1][5], "fp7x"))
236 else if(!strcmp(&argv
[1][5], "ip3g"))
238 else if(!strcmp(&argv
[1][5], "ip4g"))
240 else if(!strcmp(&argv
[1][5], "mini"))
242 else if(!strcmp(&argv
[1][5], "iax5"))
244 else if(!strcmp(&argv
[1][5], "mn2g"))
246 else if(!strcmp(&argv
[1][5], "h10"))
248 else if(!strcmp(&argv
[1][5], "h10_5gb"))
250 else if(!strcmp(&argv
[1][5], "tpj2"))
252 else if(!strcmp(&argv
[1][5], "e200"))
254 else if(!strcmp(&argv
[1][5], "iam5"))
256 else if(!strcmp(&argv
[1][5], "giga"))
258 else if(!strcmp(&argv
[1][5], "1g2g"))
260 else if(!strcmp(&argv
[1][5], "c200"))
262 else if(!strcmp(&argv
[1][5], "gigs"))
264 else if(!strcmp(&argv
[1][5], "m500"))
266 else if(!strcmp(&argv
[1][5], "m100"))
268 else if(!strcmp(&argv
[1][5], "d2"))
270 else if(!strcmp(&argv
[1][5], "iam3"))
272 else if(!strcmp(&argv
[1][5], "zvm"))
275 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
278 /* we store a 4-letter model name too, for humans */
279 strcpy(modelname
, &argv
[1][5]);
280 chksum
= modelnum
; /* start checksum calcs with this */
283 else if(!strcmp(argv
[1], "-iriver")) {
284 /* iRiver code dealt with in the iriver.c code */
287 iriver_encode(iname
, oname
, FALSE
);
290 else if(!strcmp(argv
[1], "-gigabeat")) {
291 /* iRiver code dealt with in the iriver.c code */
294 gigabeat_code(iname
, oname
);
297 else if(!strcmp(argv
[1], "-gigabeats")) {
300 gigabeat_s_code(iname
, oname
);
303 else if(!strcmp(argv
[1], "-iaudiox5")) {
306 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
308 else if(!strcmp(argv
[1], "-iaudiox5v")) {
311 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
313 else if(!strcmp(argv
[1], "-iaudiom5")) {
316 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
318 else if(!strcmp(argv
[1], "-iaudiom3")) {
321 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
323 else if(!strcmp(argv
[1], "-ipod3g")) {
326 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
328 else if(!strcmp(argv
[1], "-ipod4g")) {
331 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
333 else if(!strcmp(argv
[1], "-ipod5g")) {
336 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
338 else if(!strncmp(argv
[1], "-creative=", 10)) {
341 if(!strcmp(&argv
[1][10], "zvm"))
342 return zvm_encode(iname
, oname
, ZENVISIONM
);
343 else if(!strcmp(&argv
[1][10], "zvm60"))
344 return zvm_encode(iname
, oname
, ZENVISIONM60
);
345 else if(!strcmp(&argv
[1][10], "zenvision"))
346 return zvm_encode(iname
, oname
, ZENVISION
);
347 else if(!strcmp(&argv
[1][10], "zenv"))
348 return zvm_encode(iname
, oname
, ZENV
);
349 else if(!strcmp(&argv
[1][10], "zen"))
350 return zvm_encode(iname
, oname
, ZEN
);
352 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
356 else if(!strncmp(argv
[1], "-mi4", 4)) {
361 if(!strcmp(&argv
[1][4], "v2")) {
362 mi4magic
= MI4_MAGIC_DEFAULT
;
363 version
= 0x00010201;
365 else if(!strcmp(&argv
[1][4], "v3")) {
366 mi4magic
= MI4_MAGIC_DEFAULT
;
367 version
= 0x00010301;
369 else if(!strcmp(&argv
[1][4], "r")) {
370 mi4magic
= MI4_MAGIC_R
;
371 version
= 0x00010301;
374 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
381 if(!strncmp(argv
[2], "-model=", 7)) {
384 strncpy(model
, &argv
[2][7], 4);
386 if(!strncmp(argv
[3], "-type=", 6)) {
389 strncpy(type
, &argv
[3][6], 4);
393 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
397 file
= fopen(iname
,"rb");
402 fseek(file
,0,SEEK_END
);
403 length
= ftell(file
);
404 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
406 if ((method
== scramble
) &&
407 ((length
+ headerlen
) >= size_limit
[model_id
])) {
408 printf("error: firmware image is %ld bytes while max size is %u!\n",
410 size_limit
[model_id
]);
415 fseek(file
,0,SEEK_SET
);
416 inbuf
= malloc(length
);
418 outbuf
= malloc(length
*2);
419 else if(method
== add
)
420 outbuf
= malloc(length
+ 8);
422 outbuf
= malloc(length
);
423 if ( !inbuf
|| !outbuf
) {
424 printf("out of memory!\n");
428 /* zero-fill the last 4 bytes to make sure there's no rubbish there
429 when we write the size-aligned file later */
430 memset(outbuf
+length
-4, 0, 4);
434 i
=fread(inbuf
,1,length
,file
);
444 for (i
= 0; i
< length
; i
++) {
445 /* add 8 unsigned bits but keep a 32 bit sum */
451 for (i
= 0; i
< length
; i
++) {
452 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
453 unsigned char data
= inbuf
[i
];
454 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
462 for (i
=0; i
<length
; i
++) {
464 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
465 outbuf
[slen
++] = inbuf
[i
];
470 /* dummy case just to silence picky compilers */
474 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
475 /* calculate checksum */
476 for (i
=0;i
<length
;i
++)
480 memset(header
, 0, sizeof header
);
485 int2be(chksum
, header
); /* checksum, big-endian */
486 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
487 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
493 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
494 telechips_encode_sum(outbuf
, length
);
498 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
499 telechips_encode_crc(outbuf
, length
);
503 if (headerlen
== 6) {
504 int2be(length
, header
);
505 header
[4] = (crc
>> 8) & 0xff;
506 header
[5] = crc
& 0xff;
512 header
[3] = 0xff; /* ??? */
514 header
[6] = (crc
>> 8) & 0xff;
515 header
[7] = crc
& 0xff;
517 header
[11] = version
;
519 header
[15] = headerlen
; /* really? */
521 int2be(length
, &header
[20]);
527 int xorlen
= strlen(xorstring
);
530 for (i
=0; i
<slen
; i
++)
531 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
533 /* calculate checksum */
534 for (i
=0; i
<slen
; i
++)
537 header
[0] = header
[2] = 'Z';
538 header
[1] = header
[3] = version
;
539 int2le(length
, &header
[4]);
540 int2le(slen
, &header
[8]);
541 int2le(crc
, &header
[12]);
546 #define MY_FIRMWARE_TYPE "Rockbox"
547 #define MY_HEADER_VERSION 1
549 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
550 header
[9]='\0'; /*shouldn't have to, but to be SURE */
551 header
[10]=MY_HEADER_VERSION
&0xFF;
552 header
[11]=(crc
>>8)&0xFF;
554 int2be(sizeof(header
), &header
[12]);
559 file
= fopen(oname
,"wb");
565 if ( !fwrite(header
,headerlen
,1,file
) ) {
570 if ( !fwrite(outbuf
,length
,1,file
) ) {
582 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
587 unsigned char *outbuf
;
589 unsigned char sum
= 0;
591 file
= fopen(iname
, "rb");
596 fseek(file
,0,SEEK_END
);
597 length
= ftell(file
);
599 fseek(file
,0,SEEK_SET
);
600 outbuf
= malloc(length
+0x1030);
603 printf("out of memory!\n");
607 len
= fread(outbuf
+0x1030, 1, length
, file
);
608 if(len
< (size_t) length
) {
613 memset(outbuf
, 0, 0x1030);
614 strcpy((char *)outbuf
, idstring
);
615 memcpy(outbuf
+0x20, iaudio_bl_flash
,
616 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
617 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
618 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
621 for(i
= 0; i
< length
;i
++)
622 sum
+= outbuf
[0x1030 + i
];
624 int2be(length
, &outbuf
[0x1024]);
625 outbuf
[0x102b] = sum
;
629 file
= fopen(oname
, "wb");
635 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
636 if(len
< (size_t)length
) {
646 /* Create an ipod firmware partition image
648 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
650 This function doesn't yet handle the Broadcom resource image for the 5g,
651 so the resulting images won't be usable.
653 This has also only been tested on an ipod Photo
656 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
658 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
679 unsigned int sum
= 0;
680 unsigned int rsrcsum
= 0;
681 unsigned char *outbuf
;
685 file
= fopen(iname
, "rb");
690 fseek(file
,0,SEEK_END
);
691 length
= ftell(file
);
693 fseek(file
,0,SEEK_SET
);
695 bufsize
=(length
+0x4600);
697 bufsize
= (bufsize
+ 0x400) & ~0x200;
700 outbuf
= malloc(bufsize
);
703 printf("out of memory!\n");
707 len
= fread(outbuf
+0x4600, 1, length
, file
);
708 if(len
< (size_t)length
) {
714 /* Calculate checksum for later use in header */
715 for(i
= 0x4600; i
< 0x4600+length
;i
++)
718 /* Clear the header area to zero */
719 memset(outbuf
, 0, 0x4600);
721 /* APPLE STOP SIGN */
722 strcpy((char *)outbuf
, apple_stop_sign
);
725 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
726 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
727 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
728 short2le(fw_ver
, &outbuf
[0x10a]);
730 /* Firmware Directory - "osos" entry */
731 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
732 int2le(0, &outbuf
[0x4208]); /* id */
733 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
734 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
735 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
736 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
737 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
738 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
739 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
741 /* "rsrc" entry (if applicable) */
743 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
747 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
748 int2le(0, &outbuf
[0x4230]); /* id */
749 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
750 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
751 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
752 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
753 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
754 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
755 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
758 file
= fopen(oname
, "wb");
764 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
765 if(len
< (size_t)length
) {