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)\n");
126 printf("\nNo option results in Archos standard player/recorder format.\n");
131 int main (int argc
, char** argv
)
133 unsigned long length
,i
,slen
=0;
134 unsigned char *inbuf
,*outbuf
;
135 unsigned short crc
=0;
136 unsigned long chksum
=0; /* 32 bit checksum */
137 unsigned char header
[24];
138 char *iname
= argv
[1];
139 char *oname
= argv
[2];
140 char *xorstring
=NULL
;
144 unsigned long modelnum
;
147 enum { none
, scramble
, xor, tcc_sum
, tcc_crc
, add
} method
= scramble
;
148 bool creative_enable_ciff
;
150 model_id
= ARCHOS_PLAYER
;
156 if(!strcmp(argv
[1], "-fm")) {
161 model_id
= ARCHOS_FMRECORDER
;
164 else if(!strcmp(argv
[1], "-v2")) {
169 model_id
= ARCHOS_V2RECORDER
;
172 else if(!strcmp(argv
[1], "-ofm")) {
177 model_id
= ARCHOS_ONDIO_FM
;
180 else if(!strcmp(argv
[1], "-osp")) {
185 model_id
= ARCHOS_ONDIO_SP
;
188 else if(!strcmp(argv
[1], "-neo")) {
194 else if(!strncmp(argv
[1], "-mm=", 4)) {
199 version
= argv
[1][4];
203 printf("Multimedia needs an xor string\n");
207 else if(!strncmp(argv
[1], "-tcc=", 4)) {
212 if(!strcmp(&argv
[1][5], "sum"))
214 else if(!strcmp(&argv
[1][5], "crc"))
217 fprintf(stderr
, "unsupported TCC method: %s\n", &argv
[1][5]);
221 else if(!strncmp(argv
[1], "-add=", 5)) {
226 if(!strcmp(&argv
[1][5], "h120"))
228 else if(!strcmp(&argv
[1][5], "h140"))
229 modelnum
= 0; /* the same as the h120 */
230 else if(!strcmp(&argv
[1][5], "h100"))
232 else if(!strcmp(&argv
[1][5], "h300"))
234 else if(!strcmp(&argv
[1][5], "ipco"))
236 else if(!strcmp(&argv
[1][5], "nano"))
238 else if(!strcmp(&argv
[1][5], "ipvd"))
240 else if(!strcmp(&argv
[1][5], "fp7x"))
242 else if(!strcmp(&argv
[1][5], "ip3g"))
244 else if(!strcmp(&argv
[1][5], "ip4g"))
246 else if(!strcmp(&argv
[1][5], "mini"))
248 else if(!strcmp(&argv
[1][5], "iax5"))
250 else if(!strcmp(&argv
[1][5], "mn2g"))
252 else if(!strcmp(&argv
[1][5], "h10"))
254 else if(!strcmp(&argv
[1][5], "h10_5gb"))
256 else if(!strcmp(&argv
[1][5], "tpj2"))
258 else if(!strcmp(&argv
[1][5], "e200"))
260 else if(!strcmp(&argv
[1][5], "iam5"))
262 else if(!strcmp(&argv
[1][5], "giga"))
264 else if(!strcmp(&argv
[1][5], "1g2g"))
266 else if(!strcmp(&argv
[1][5], "c200"))
268 else if(!strcmp(&argv
[1][5], "gigs"))
270 else if(!strcmp(&argv
[1][5], "m500"))
272 else if(!strcmp(&argv
[1][5], "m100"))
274 else if(!strcmp(&argv
[1][5], "d2"))
276 else if(!strcmp(&argv
[1][5], "iam3"))
278 else if(!strcmp(&argv
[1][5], "9200")) /* Philips SA9200 */
280 else if(!strcmp(&argv
[1][5], "1630")) /* Philips HDD1630 */
282 else if (!strcmp(&argv
[1][5], "i7"))
285 fprintf(stderr
, "unsupported model: %s\n", &argv
[1][5]);
288 /* we store a 4-letter model name too, for humans */
289 strcpy(modelname
, &argv
[1][5]);
290 chksum
= modelnum
; /* start checksum calcs with this */
293 else if(!strcmp(argv
[1], "-iriver")) {
294 /* iRiver code dealt with in the iriver.c code */
297 return (iriver_encode(iname
, oname
, FALSE
) != 0) ? -1 : 0;
299 else if(!strcmp(argv
[1], "-gigabeat")) {
300 /* iRiver code dealt with in the iriver.c code */
303 gigabeat_code(iname
, oname
);
306 else if(!strcmp(argv
[1], "-gigabeats")) {
309 gigabeat_s_code(iname
, oname
);
312 else if(!strcmp(argv
[1], "-iaudiox5")) {
315 return iaudio_encode(iname
, oname
, "COWON_X5_FW");
317 else if(!strcmp(argv
[1], "-iaudiox5v")) {
320 return iaudio_encode(iname
, oname
, "COWON_X5V_FW");
322 else if(!strcmp(argv
[1], "-iaudiom5")) {
325 return iaudio_encode(iname
, oname
, "COWON_M5_FW");
327 else if(!strcmp(argv
[1], "-iaudiom3")) {
330 return iaudio_encode(iname
, oname
, "COWON_M3_FW");
332 else if(!strcmp(argv
[1], "-ipod3g")) {
335 return ipod_encode(iname
, oname
, 2, false); /* Firmware image v2 */
337 else if(!strcmp(argv
[1], "-ipod4g")) {
340 return ipod_encode(iname
, oname
, 3, false); /* Firmware image v3 */
342 else if(!strcmp(argv
[1], "-ipod5g")) {
345 return ipod_encode(iname
, oname
, 3, true); /* Firmware image v3 */
347 else if(!strncmp(argv
[1], "-creative=", 10))
349 if(!strcmp(argv
[2], "-no-ciff"))
351 creative_enable_ciff
= false;
357 creative_enable_ciff
= true;
361 if(!strcmp(&argv
[1][10], "zvm"))
362 return zvm_encode(iname
, oname
, ZENVISIONM
, creative_enable_ciff
);
363 else if(!strcmp(&argv
[1][10], "zvm60"))
364 return zvm_encode(iname
, oname
, ZENVISIONM60
, creative_enable_ciff
);
365 else if(!strcmp(&argv
[1][10], "zenvision"))
366 return zvm_encode(iname
, oname
, ZENVISION
, creative_enable_ciff
);
367 else if(!strcmp(&argv
[1][10], "zenv"))
368 return zvm_encode(iname
, oname
, ZENV
, creative_enable_ciff
);
369 else if(!strcmp(&argv
[1][10], "zen"))
370 return zvm_encode(iname
, oname
, ZEN
, creative_enable_ciff
);
373 fprintf(stderr
, "unsupported Creative device: %s\n", &argv
[1][10]);
377 else if(!strncmp(argv
[1], "-mi4", 4)) {
382 if(!strcmp(&argv
[1][4], "v2")) {
383 mi4magic
= MI4_MAGIC_DEFAULT
;
384 version
= 0x00010201;
386 else if(!strcmp(&argv
[1][4], "v3")) {
387 mi4magic
= MI4_MAGIC_DEFAULT
;
388 version
= 0x00010301;
390 else if(!strcmp(&argv
[1][4], "r")) {
391 mi4magic
= MI4_MAGIC_R
;
392 version
= 0x00010301;
395 printf( "Invalid mi4 version: %s\n", &argv
[1][4]);
402 if(!strncmp(argv
[2], "-model=", 7)) {
405 strncpy(model
, &argv
[2][7], 4);
407 if(!strncmp(argv
[3], "-type=", 6)) {
410 strncpy(type
, &argv
[3][6], 4);
414 return mi4_encode(iname
, oname
, version
, mi4magic
, model
, type
);
418 file
= fopen(iname
,"rb");
423 fseek(file
,0,SEEK_END
);
424 length
= ftell(file
);
425 length
= (length
+ 3) & ~3; /* Round up to nearest 4 byte boundary */
427 if ((method
== scramble
) &&
428 ((length
+ headerlen
) >= size_limit
[model_id
])) {
429 printf("error: firmware image is %ld bytes while max size is %u!\n",
431 size_limit
[model_id
]);
436 fseek(file
,0,SEEK_SET
);
437 inbuf
= malloc(length
);
439 outbuf
= malloc(length
*2);
440 else if(method
== add
)
441 outbuf
= malloc(length
+ 8);
443 outbuf
= malloc(length
);
444 if ( !inbuf
|| !outbuf
) {
445 printf("out of memory!\n");
449 /* zero-fill the last 4 bytes to make sure there's no rubbish there
450 when we write the size-aligned file later */
451 memset(outbuf
+length
-4, 0, 4);
455 i
=fread(inbuf
,1,length
,file
);
465 for (i
= 0; i
< length
; i
++) {
466 /* add 8 unsigned bits but keep a 32 bit sum */
472 for (i
= 0; i
< length
; i
++) {
473 unsigned long addr
= (i
>> 2) + ((i
% 4) * slen
);
474 unsigned char data
= inbuf
[i
];
475 data
= ~((data
<< 1) | ((data
>> 7) & 1)); /* poor man's ROL */
483 for (i
=0; i
<length
; i
++) {
485 outbuf
[slen
++] = 0xff; /* all data is uncompressed */
486 outbuf
[slen
++] = inbuf
[i
];
491 /* dummy case just to silence picky compilers */
495 if((method
== none
) || (method
== scramble
) || (method
== xor)) {
496 /* calculate checksum */
497 for (i
=0;i
<length
;i
++)
501 memset(header
, 0, sizeof header
);
506 int2be(chksum
, header
); /* checksum, big-endian */
507 memcpy(&header
[4], modelname
, 4); /* 4 bytes model name */
508 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
514 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
515 telechips_encode_sum(outbuf
, length
);
519 memcpy(outbuf
, inbuf
, length
); /* the input buffer to output*/
520 telechips_encode_crc(outbuf
, length
);
524 if (headerlen
== 6) {
525 int2be(length
, header
);
526 header
[4] = (crc
>> 8) & 0xff;
527 header
[5] = crc
& 0xff;
533 header
[3] = 0xff; /* ??? */
535 header
[6] = (crc
>> 8) & 0xff;
536 header
[7] = crc
& 0xff;
538 header
[11] = version
;
540 header
[15] = headerlen
; /* really? */
542 int2be(length
, &header
[20]);
548 int xorlen
= strlen(xorstring
);
551 for (i
=0; i
<slen
; i
++)
552 outbuf
[i
] ^= xorstring
[i
& (xorlen
-1)];
554 /* calculate checksum */
555 for (i
=0; i
<slen
; i
++)
558 header
[0] = header
[2] = 'Z';
559 header
[1] = header
[3] = version
;
560 int2le(length
, &header
[4]);
561 int2le(slen
, &header
[8]);
562 int2le(crc
, &header
[12]);
567 #define MY_FIRMWARE_TYPE "Rockbox"
568 #define MY_HEADER_VERSION 1
570 strncpy((char *)header
, MY_FIRMWARE_TYPE
,9);
571 header
[9]='\0'; /*shouldn't have to, but to be SURE */
572 header
[10]=MY_HEADER_VERSION
&0xFF;
573 header
[11]=(crc
>>8)&0xFF;
575 int2be(sizeof(header
), &header
[12]);
580 file
= fopen(oname
,"wb");
586 if ( !fwrite(header
,headerlen
,1,file
) ) {
591 if ( !fwrite(outbuf
,length
,1,file
) ) {
603 int iaudio_encode(char *iname
, char *oname
, char *idstring
)
608 unsigned char *outbuf
;
610 unsigned char sum
= 0;
612 file
= fopen(iname
, "rb");
617 fseek(file
,0,SEEK_END
);
618 length
= ftell(file
);
620 fseek(file
,0,SEEK_SET
);
621 outbuf
= malloc(length
+0x1030);
624 printf("out of memory!\n");
628 len
= fread(outbuf
+0x1030, 1, length
, file
);
629 if(len
< (size_t) length
) {
634 memset(outbuf
, 0, 0x1030);
635 strcpy((char *)outbuf
, idstring
);
636 memcpy(outbuf
+0x20, iaudio_bl_flash
,
637 BMPWIDTH_iaudio_bl_flash
* (BMPHEIGHT_iaudio_bl_flash
/8) * 2);
638 short2be(BMPWIDTH_iaudio_bl_flash
, &outbuf
[0x10]);
639 short2be((BMPHEIGHT_iaudio_bl_flash
/8), &outbuf
[0x12]);
642 for(i
= 0; i
< length
;i
++)
643 sum
+= outbuf
[0x1030 + i
];
645 int2be(length
, &outbuf
[0x1024]);
646 outbuf
[0x102b] = sum
;
650 file
= fopen(oname
, "wb");
656 len
= fwrite(outbuf
, 1, length
+0x1030, file
);
657 if(len
< (size_t)length
) {
667 /* Create an ipod firmware partition image
669 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
671 This function doesn't yet handle the Broadcom resource image for the 5g,
672 so the resulting images won't be usable.
674 This has also only been tested on an ipod Photo
677 int ipod_encode(char *iname
, char *oname
, int fw_ver
, bool fake_rsrc
)
679 static const char *apple_stop_sign
= "{{~~ /-----\\ "\
700 unsigned int sum
= 0;
701 unsigned int rsrcsum
= 0;
702 unsigned char *outbuf
;
706 file
= fopen(iname
, "rb");
711 fseek(file
,0,SEEK_END
);
712 length
= ftell(file
);
714 fseek(file
,0,SEEK_SET
);
716 bufsize
=(length
+0x4600);
718 bufsize
= (bufsize
+ 0x400) & ~0x200;
721 outbuf
= malloc(bufsize
);
724 printf("out of memory!\n");
728 len
= fread(outbuf
+0x4600, 1, length
, file
);
729 if(len
< (size_t)length
) {
735 /* Calculate checksum for later use in header */
736 for(i
= 0x4600; i
< 0x4600+length
;i
++)
739 /* Clear the header area to zero */
740 memset(outbuf
, 0, 0x4600);
742 /* APPLE STOP SIGN */
743 strcpy((char *)outbuf
, apple_stop_sign
);
746 memcpy(&outbuf
[0x100],"]ih[",4); /* Magic */
747 int2le(0x4000, &outbuf
[0x104]); /* Firmware offset relative to 0x200 */
748 short2le(0x10c, &outbuf
[0x108]); /* Location of extended header */
749 short2le(fw_ver
, &outbuf
[0x10a]);
751 /* Firmware Directory - "osos" entry */
752 memcpy(&outbuf
[0x4200],"!ATAsoso",8); /* dev and type */
753 int2le(0, &outbuf
[0x4208]); /* id */
754 int2le(0x4400, &outbuf
[0x420c]); /* devOffset */
755 int2le(length
, &outbuf
[0x4210]); /* Length of firmware */
756 int2le(0x10000000, &outbuf
[0x4214]); /* Addr */
757 int2le(0, &outbuf
[0x4218]); /* Entry Offset */
758 int2le(sum
, &outbuf
[0x421c]); /* Checksum */
759 int2le(0x00006012, &outbuf
[0x4220]); /* vers - 0x6012 is a guess */
760 int2le(0xffffffff, &outbuf
[0x4224]); /* LoadAddr - for flash images */
762 /* "rsrc" entry (if applicable) */
764 rsrcoffset
=(length
+0x4600+0x200) & ~0x200;
768 memcpy(&outbuf
[0x4228],"!ATAcrsr",8); /* dev and type */
769 int2le(0, &outbuf
[0x4230]); /* id */
770 int2le(rsrcoffset
, &outbuf
[0x4234]); /* devOffset */
771 int2le(rsrclength
, &outbuf
[0x4238]); /* Length of firmware */
772 int2le(0x10000000, &outbuf
[0x423c]); /* Addr */
773 int2le(0, &outbuf
[0x4240]); /* Entry Offset */
774 int2le(rsrcsum
, &outbuf
[0x4244]); /* Checksum */
775 int2le(0x0000b000, &outbuf
[0x4248]); /* vers */
776 int2le(0xffffffff, &outbuf
[0x424c]); /* LoadAddr - for flash images */
779 file
= fopen(oname
, "wb");
785 len
= fwrite(outbuf
, 1, length
+0x4600, file
);
786 if(len
< (size_t)length
) {