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)\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"))
273 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
276 /* we store a 4-letter model name too, for humans */
277 strcpy(modelname
, &argv
[1][5]);
278 chksum
= modelnum
; /* start checksum calcs with this */
281 else if(!strcmp(argv
[1], "-iriver")) {
282 /* iRiver code dealt with in the iriver.c code */
285 iriver_encode(iname
, oname
, FALSE
);
288 else if(!strcmp(argv
[1], "-gigabeat")) {
289 /* iRiver code dealt with in the iriver.c code */
292 gigabeat_code(iname
, oname
);
295 else if(!strcmp(argv
[1], "-gigabeats")) {
298 gigabeat_s_code(iname
, oname
);
301 else if(!strcmp(argv
[1], "-iaudiox5")) {
304 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
306 else if(!strcmp(argv
[1], "-iaudiox5v")) {
309 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
311 else if(!strcmp(argv
[1], "-iaudiom5")) {
314 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
316 else if(!strcmp(argv
[1], "-iaudiom3")) {
319 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
321 else if(!strcmp(argv
[1], "-ipod3g")) {
324 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
326 else if(!strcmp(argv
[1], "-ipod4g")) {
329 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
331 else if(!strcmp(argv
[1], "-ipod5g")) {
334 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
336 else if(!strncmp(argv
[1], "-creative=", 10)) {
339 if(!strcmp(&argv
[1][10], "zvm"))
340 return zvm_encode(iname
, oname
, ZENVISIONM
);
341 else if(!strcmp(&argv
[1][10], "zvm60"))
342 return zvm_encode(iname
, oname
, ZENVISIONM60
);
343 else if(!strcmp(&argv
[1][10], "zenvision"))
344 return zvm_encode(iname
, oname
, ZENVISION
);
345 else if(!strcmp(&argv
[1][10], "zenv"))
346 return zvm_encode(iname
, oname
, ZENV
);
348 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
352 else if(!strncmp(argv
[1], "-mi4", 4)) {
357 if(!strcmp(&argv
[1][4], "v2")) {
358 mi4magic
= MI4_MAGIC_DEFAULT
;
359 version
= 0x00010201;
361 else if(!strcmp(&argv
[1][4], "v3")) {
362 mi4magic
= MI4_MAGIC_DEFAULT
;
363 version
= 0x00010301;
365 else if(!strcmp(&argv
[1][4], "r")) {
366 mi4magic
= MI4_MAGIC_R
;
367 version
= 0x00010301;
370 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
377 if(!strncmp(argv
[2], "-model=", 7)) {
380 strncpy(model
, &argv
[2][7], 4);
382 if(!strncmp(argv
[3], "-type=", 6)) {
385 strncpy(type
, &argv
[3][6], 4);
389 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
393 file
= fopen(iname
,"rb");
398 fseek(file
,0,SEEK_END
);
399 length
= ftell(file
);
400 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
402 if ((method
== scramble
) &&
403 ((length
+ headerlen
) >= size_limit
[model_id
])) {
404 printf("error: firmware image is %ld bytes while max size is %u!\n",
406 size_limit
[model_id
]);
411 fseek(file
,0,SEEK_SET
);
412 inbuf
= malloc(length
);
414 outbuf
= malloc(length
*2);
415 else if(method
== add
)
416 outbuf
= malloc(length
+ 8);
418 outbuf
= malloc(length
);
419 if ( !inbuf
|| !outbuf
) {
420 printf("out of memory!\n");
424 /* zero-fill the last 4 bytes to make sure there's no rubbish there
425 when we write the size-aligned file later */
426 memset(outbuf
+length
-4, 0, 4);
430 i
=fread(inbuf
,1,length
,file
);
440 for (i
= 0; i
< length
; i
++) {
441 /* add 8 unsigned bits but keep a 32 bit sum */
447 for (i
= 0; i
< length
; i
++) {
448 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
449 unsigned char data
= inbuf
[i
];
450 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
458 for (i
=0; i
<length
; i
++) {
460 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
461 outbuf
[slen
++] = inbuf
[i
];
466 /* dummy case just to silence picky compilers */
470 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
471 /* calculate checksum */
472 for (i
=0;i
<length
;i
++)
476 memset(header
, 0, sizeof header
);
481 int2be(chksum
, header
); /* checksum, big-endian */
482 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
483 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
489 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
490 telechips_encode_sum(outbuf
, length
);
494 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
495 telechips_encode_crc(outbuf
, length
);
499 if (headerlen
== 6) {
500 int2be(length
, header
);
501 header
[4] = (crc
>> 8) & 0xff;
502 header
[5] = crc
& 0xff;
508 header
[3] = 0xff; /* ??? */
510 header
[6] = (crc
>> 8) & 0xff;
511 header
[7] = crc
& 0xff;
513 header
[11] = version
;
515 header
[15] = headerlen
; /* really? */
517 int2be(length
, &header
[20]);
523 int xorlen
= strlen(xorstring
);
526 for (i
=0; i
<slen
; i
++)
527 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
529 /* calculate checksum */
530 for (i
=0; i
<slen
; i
++)
533 header
[0] = header
[2] = 'Z';
534 header
[1] = header
[3] = version
;
535 int2le(length
, &header
[4]);
536 int2le(slen
, &header
[8]);
537 int2le(crc
, &header
[12]);
542 #define MY_FIRMWARE_TYPE "Rockbox"
543 #define MY_HEADER_VERSION 1
545 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
546 header
[9]='\0'; /*shouldn't have to, but to be SURE */
547 header
[10]=MY_HEADER_VERSION
&0xFF;
548 header
[11]=(crc
>>8)&0xFF;
550 int2be(sizeof(header
), &header
[12]);
555 file
= fopen(oname
,"wb");
561 if ( !fwrite(header
,headerlen
,1,file
) ) {
566 if ( !fwrite(outbuf
,length
,1,file
) ) {
578 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
583 unsigned char *outbuf
;
585 unsigned char sum
= 0;
587 file
= fopen(iname
, "rb");
592 fseek(file
,0,SEEK_END
);
593 length
= ftell(file
);
595 fseek(file
,0,SEEK_SET
);
596 outbuf
= malloc(length
+0x1030);
599 printf("out of memory!\n");
603 len
= fread(outbuf
+0x1030, 1, length
, file
);
604 if(len
< (size_t) length
) {
609 memset(outbuf
, 0, 0x1030);
610 strcpy((char *)outbuf
, idstring
);
611 memcpy(outbuf
+0x20, iaudio_bl_flash
,
612 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
613 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
614 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
617 for(i
= 0; i
< length
;i
++)
618 sum
+= outbuf
[0x1030 + i
];
620 int2be(length
, &outbuf
[0x1024]);
621 outbuf
[0x102b] = sum
;
625 file
= fopen(oname
, "wb");
631 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
632 if(len
< (size_t)length
) {
642 /* Create an ipod firmware partition image
644 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
646 This function doesn't yet handle the Broadcom resource image for the 5g,
647 so the resulting images won't be usable.
649 This has also only been tested on an ipod Photo
652 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
654 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
675 unsigned int sum
= 0;
676 unsigned int rsrcsum
= 0;
677 unsigned char *outbuf
;
681 file
= fopen(iname
, "rb");
686 fseek(file
,0,SEEK_END
);
687 length
= ftell(file
);
689 fseek(file
,0,SEEK_SET
);
691 bufsize
=(length
+0x4600);
693 bufsize
= (bufsize
+ 0x400) & ~0x200;
696 outbuf
= malloc(bufsize
);
699 printf("out of memory!\n");
703 len
= fread(outbuf
+0x4600, 1, length
, file
);
704 if(len
< (size_t)length
) {
710 /* Calculate checksum for later use in header */
711 for(i
= 0x4600; i
< 0x4600+length
;i
++)
714 /* Clear the header area to zero */
715 memset(outbuf
, 0, 0x4600);
717 /* APPLE STOP SIGN */
718 strcpy((char *)outbuf
, apple_stop_sign
);
721 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
722 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
723 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
724 short2le(fw_ver
, &outbuf
[0x10a]);
726 /* Firmware Directory - "osos" entry */
727 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
728 int2le(0, &outbuf
[0x4208]); /* id */
729 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
730 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
731 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
732 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
733 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
734 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
735 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
737 /* "rsrc" entry (if applicable) */
739 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
743 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
744 int2le(0, &outbuf
[0x4230]); /* id */
745 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
746 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
747 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
748 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
749 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
750 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
751 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
754 file
= fopen(oname
, "wb");
760 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
761 if(len
< (size_t)length
) {