Rename variables sectorbuf and verbose to avoid clashes in rbutil. Cleanup exports...
[Rockbox.git] / tools / scramble.c
blobc02c78916bbd9f36bf4e854b1c5df50449280c36
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdbool.h>
23 #include <string.h>
24 #include "iriver.h"
25 #include "gigabeat.h"
26 #include "gigabeats.h"
27 #include "mi4.h"
28 #include "telechips.h"
29 #include "creative.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);
35 enum
37 ARCHOS_PLAYER, /* and V1 recorder */
38 ARCHOS_V2RECORDER,
39 ARCHOS_FMRECORDER,
40 ARCHOS_ONDIO_SP,
41 ARCHOS_ONDIO_FM
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)
55 addr[0] = val & 0xFF;
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];
63 return res;
66 void int2le(unsigned int val, unsigned char* addr)
68 addr[0] = val & 0xFF;
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;
79 addr[3] = val & 0xFF;
82 void short2be(unsigned short val, unsigned char* addr)
84 addr[0] = (val >> 8) & 0xff;
85 addr[1] = val & 0xFF;
88 void usage(void)
90 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
91 printf("options:\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 (X values: zvm, zvm60, zenvision\n"
108 "\t zenv, zen\n");
109 printf("\t-gigabeat Toshiba Gigabeat F/X format\n"
110 "\t-gigabeats Toshiba Gigabeat S format\n"
111 "\t-mi4v2 PortalPlayer .mi4 format (revision 010201)\n"
112 "\t-mi4v3 PortalPlayer .mi4 format (revision 010301)\n"
113 "\t-mi4r Sandisk Rhapsody .mi4 format\n"
114 "\t All mi4 options take two optional arguments:\n");
115 printf("\t -model=XXXX where XXXX is the model id string\n"
116 "\t -type=XXXX where XXXX is a string indicating the \n"
117 "\t type of binary, eg. RBOS, RBBL\n"
118 "\t-tcc=X Telechips generic firmware format (X values: sum, crc)\n"
119 "\t-add=X Rockbox generic \"add-up\" checksum format\n"
120 "\t (X values: h100, h120, h140, h300, ipco, nano, ipvd, mn2g\n"
121 "\t ip3g, ip4g, mini, iax5, iam5, iam3, h10, h10_5gb,\n"
122 "\t tpj2, c200, e200, giga, gigs, m100, m500, d2,\n");
123 printf("\t 9200)\n");
124 printf("\nNo option results in Archos standard player/recorder format.\n");
126 exit(1);
129 int main (int argc, char** argv)
131 unsigned long length,i,slen=0;
132 unsigned char *inbuf,*outbuf;
133 unsigned short crc=0;
134 unsigned long chksum=0; /* 32 bit checksum */
135 unsigned char header[24];
136 char *iname = argv[1];
137 char *oname = argv[2];
138 char *xorstring=NULL;
139 int headerlen = 6;
140 FILE* file;
141 int version=0;
142 unsigned long modelnum;
143 char modelname[5];
144 int model_id;
145 enum { none, scramble, xor, tcc_sum, tcc_crc, add } method = scramble;
147 model_id = ARCHOS_PLAYER;
149 if (argc < 3) {
150 usage();
153 if(!strcmp(argv[1], "-fm")) {
154 headerlen = 24;
155 iname = argv[2];
156 oname = argv[3];
157 version = 4;
158 model_id = ARCHOS_FMRECORDER;
161 else if(!strcmp(argv[1], "-v2")) {
162 headerlen = 24;
163 iname = argv[2];
164 oname = argv[3];
165 version = 2;
166 model_id = ARCHOS_V2RECORDER;
169 else if(!strcmp(argv[1], "-ofm")) {
170 headerlen = 24;
171 iname = argv[2];
172 oname = argv[3];
173 version = 8;
174 model_id = ARCHOS_ONDIO_FM;
177 else if(!strcmp(argv[1], "-osp")) {
178 headerlen = 24;
179 iname = argv[2];
180 oname = argv[3];
181 version = 16;
182 model_id = ARCHOS_ONDIO_SP;
185 else if(!strcmp(argv[1], "-neo")) {
186 headerlen = 17;
187 iname = argv[2];
188 oname = argv[3];
189 method = none;
191 else if(!strncmp(argv[1], "-mm=", 4)) {
192 headerlen = 16;
193 iname = argv[2];
194 oname = argv[3];
195 method = xor;
196 version = argv[1][4];
197 if (argc > 4)
198 xorstring = argv[4];
199 else {
200 printf("Multimedia needs an xor string\n");
201 return -1;
204 else if(!strncmp(argv[1], "-tcc=", 4)) {
205 headerlen = 0;
206 iname = argv[2];
207 oname = argv[3];
209 if(!strcmp(&argv[1][5], "sum"))
210 method = tcc_sum;
211 else if(!strcmp(&argv[1][5], "crc"))
212 method = tcc_crc;
213 else {
214 fprintf(stderr, "unsupported TCC method: %s\n", &argv[1][5]);
215 return 2;
218 else if(!strncmp(argv[1], "-add=", 5)) {
219 iname = argv[2];
220 oname = argv[3];
221 method = add;
223 if(!strcmp(&argv[1][5], "h120"))
224 modelnum = 0;
225 else if(!strcmp(&argv[1][5], "h140"))
226 modelnum = 0; /* the same as the h120 */
227 else if(!strcmp(&argv[1][5], "h100"))
228 modelnum = 1;
229 else if(!strcmp(&argv[1][5], "h300"))
230 modelnum = 2;
231 else if(!strcmp(&argv[1][5], "ipco"))
232 modelnum = 3;
233 else if(!strcmp(&argv[1][5], "nano"))
234 modelnum = 4;
235 else if(!strcmp(&argv[1][5], "ipvd"))
236 modelnum = 5;
237 else if(!strcmp(&argv[1][5], "fp7x"))
238 modelnum = 6;
239 else if(!strcmp(&argv[1][5], "ip3g"))
240 modelnum = 7;
241 else if(!strcmp(&argv[1][5], "ip4g"))
242 modelnum = 8;
243 else if(!strcmp(&argv[1][5], "mini"))
244 modelnum = 9;
245 else if(!strcmp(&argv[1][5], "iax5"))
246 modelnum = 10;
247 else if(!strcmp(&argv[1][5], "mn2g"))
248 modelnum = 11;
249 else if(!strcmp(&argv[1][5], "h10"))
250 modelnum = 13;
251 else if(!strcmp(&argv[1][5], "h10_5gb"))
252 modelnum = 14;
253 else if(!strcmp(&argv[1][5], "tpj2"))
254 modelnum = 15;
255 else if(!strcmp(&argv[1][5], "e200"))
256 modelnum = 16;
257 else if(!strcmp(&argv[1][5], "iam5"))
258 modelnum = 17;
259 else if(!strcmp(&argv[1][5], "giga"))
260 modelnum = 18;
261 else if(!strcmp(&argv[1][5], "1g2g"))
262 modelnum = 19;
263 else if(!strcmp(&argv[1][5], "c200"))
264 modelnum = 20;
265 else if(!strcmp(&argv[1][5], "gigs"))
266 modelnum = 21;
267 else if(!strcmp(&argv[1][5], "m500"))
268 modelnum = 22;
269 else if(!strcmp(&argv[1][5], "m100"))
270 modelnum = 23;
271 else if(!strcmp(&argv[1][5], "d2"))
272 modelnum = 24;
273 else if(!strcmp(&argv[1][5], "iam3"))
274 modelnum = 25;
275 else if(!strcmp(&argv[1][5], "9200")) /* Philips SA9200 */
276 modelnum = 26;
277 else {
278 fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
279 return 2;
281 /* we store a 4-letter model name too, for humans */
282 strcpy(modelname, &argv[1][5]);
283 chksum = modelnum; /* start checksum calcs with this */
286 else if(!strcmp(argv[1], "-iriver")) {
287 /* iRiver code dealt with in the iriver.c code */
288 iname = argv[2];
289 oname = argv[3];
290 iriver_encode(iname, oname, FALSE);
291 return 0;
293 else if(!strcmp(argv[1], "-gigabeat")) {
294 /* iRiver code dealt with in the iriver.c code */
295 iname = argv[2];
296 oname = argv[3];
297 gigabeat_code(iname, oname);
298 return 0;
300 else if(!strcmp(argv[1], "-gigabeats")) {
301 iname = argv[2];
302 oname = argv[3];
303 gigabeat_s_code(iname, oname);
304 return 0;
306 else if(!strcmp(argv[1], "-iaudiox5")) {
307 iname = argv[2];
308 oname = argv[3];
309 return iaudio_encode(iname, oname, "COWON_X5_FW");
311 else if(!strcmp(argv[1], "-iaudiox5v")) {
312 iname = argv[2];
313 oname = argv[3];
314 return iaudio_encode(iname, oname, "COWON_X5V_FW");
316 else if(!strcmp(argv[1], "-iaudiom5")) {
317 iname = argv[2];
318 oname = argv[3];
319 return iaudio_encode(iname, oname, "COWON_M5_FW");
321 else if(!strcmp(argv[1], "-iaudiom3")) {
322 iname = argv[2];
323 oname = argv[3];
324 return iaudio_encode(iname, oname, "COWON_M3_FW");
326 else if(!strcmp(argv[1], "-ipod3g")) {
327 iname = argv[2];
328 oname = argv[3];
329 return ipod_encode(iname, oname, 2, false); /* Firmware image v2 */
331 else if(!strcmp(argv[1], "-ipod4g")) {
332 iname = argv[2];
333 oname = argv[3];
334 return ipod_encode(iname, oname, 3, false); /* Firmware image v3 */
336 else if(!strcmp(argv[1], "-ipod5g")) {
337 iname = argv[2];
338 oname = argv[3];
339 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
341 else if(!strncmp(argv[1], "-creative=", 10)) {
342 iname = argv[2];
343 oname = argv[3];
344 if(!strcmp(&argv[1][10], "zvm"))
345 return zvm_encode(iname, oname, ZENVISIONM);
346 else if(!strcmp(&argv[1][10], "zvm60"))
347 return zvm_encode(iname, oname, ZENVISIONM60);
348 else if(!strcmp(&argv[1][10], "zenvision"))
349 return zvm_encode(iname, oname, ZENVISION);
350 else if(!strcmp(&argv[1][10], "zenv"))
351 return zvm_encode(iname, oname, ZENV);
352 else if(!strcmp(&argv[1][10], "zen"))
353 return zvm_encode(iname, oname, ZEN);
354 else {
355 fprintf(stderr, "unsupported Creative device: %s\n", &argv[1][10]);
356 return 2;
359 else if(!strncmp(argv[1], "-mi4", 4)) {
360 int mi4magic;
361 char model[4] = "";
362 char type[4] = "";
364 if(!strcmp(&argv[1][4], "v2")) {
365 mi4magic = MI4_MAGIC_DEFAULT;
366 version = 0x00010201;
368 else if(!strcmp(&argv[1][4], "v3")) {
369 mi4magic = MI4_MAGIC_DEFAULT;
370 version = 0x00010301;
372 else if(!strcmp(&argv[1][4], "r")) {
373 mi4magic = MI4_MAGIC_R;
374 version = 0x00010301;
376 else {
377 printf( "Invalid mi4 version: %s\n", &argv[1][4]);
378 return -1;
381 iname = argv[2];
382 oname = argv[3];
384 if(!strncmp(argv[2], "-model=", 7)) {
385 iname = argv[3];
386 oname = argv[4];
387 strncpy(model, &argv[2][7], 4);
389 if(!strncmp(argv[3], "-type=", 6)) {
390 iname = argv[4];
391 oname = argv[5];
392 strncpy(type, &argv[3][6], 4);
396 return mi4_encode(iname, oname, version, mi4magic, model, type);
399 /* open file */
400 file = fopen(iname,"rb");
401 if (!file) {
402 perror(iname);
403 return -1;
405 fseek(file,0,SEEK_END);
406 length = ftell(file);
407 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
409 if ((method == scramble) &&
410 ((length + headerlen) >= size_limit[model_id])) {
411 printf("error: firmware image is %ld bytes while max size is %u!\n",
412 length + headerlen,
413 size_limit[model_id]);
414 fclose(file);
415 return -1;
418 fseek(file,0,SEEK_SET);
419 inbuf = malloc(length);
420 if (method == xor)
421 outbuf = malloc(length*2);
422 else if(method == add)
423 outbuf = malloc(length + 8);
424 else
425 outbuf = malloc(length);
426 if ( !inbuf || !outbuf ) {
427 printf("out of memory!\n");
428 return -1;
430 if(length> 4) {
431 /* zero-fill the last 4 bytes to make sure there's no rubbish there
432 when we write the size-aligned file later */
433 memset(outbuf+length-4, 0, 4);
436 /* read file */
437 i=fread(inbuf,1,length,file);
438 if ( !i ) {
439 perror(iname);
440 return -1;
442 fclose(file);
444 switch (method)
446 case add:
447 for (i = 0; i < length; i++) {
448 /* add 8 unsigned bits but keep a 32 bit sum */
449 chksum += inbuf[i];
451 break;
452 case scramble:
453 slen = length/4;
454 for (i = 0; i < length; i++) {
455 unsigned long addr = (i >> 2) + ((i % 4) * slen);
456 unsigned char data = inbuf[i];
457 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
458 outbuf[addr] = data;
460 break;
462 case xor:
463 /* "compress" */
464 slen = 0;
465 for (i=0; i<length; i++) {
466 if (!(i&7))
467 outbuf[slen++] = 0xff; /* all data is uncompressed */
468 outbuf[slen++] = inbuf[i];
470 break;
471 case none:
472 default:
473 /* dummy case just to silence picky compilers */
474 break;
477 if((method == none) || (method == scramble) || (method == xor)) {
478 /* calculate checksum */
479 for (i=0;i<length;i++)
480 crc += inbuf[i];
483 memset(header, 0, sizeof header);
484 switch (method)
486 case add:
488 int2be(chksum, header); /* checksum, big-endian */
489 memcpy(&header[4], modelname, 4); /* 4 bytes model name */
490 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
491 headerlen = 8;
493 break;
495 case tcc_sum:
496 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
497 telechips_encode_sum(outbuf, length);
498 break;
500 case tcc_crc:
501 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
502 telechips_encode_crc(outbuf, length);
503 break;
505 case scramble:
506 if (headerlen == 6) {
507 int2be(length, header);
508 header[4] = (crc >> 8) & 0xff;
509 header[5] = crc & 0xff;
511 else {
512 header[0] =
513 header[1] =
514 header[2] =
515 header[3] = 0xff; /* ??? */
517 header[6] = (crc >> 8) & 0xff;
518 header[7] = crc & 0xff;
520 header[11] = version;
522 header[15] = headerlen; /* really? */
524 int2be(length, &header[20]);
526 break;
528 case xor:
530 int xorlen = strlen(xorstring);
532 /* xor data */
533 for (i=0; i<slen; i++)
534 outbuf[i] ^= xorstring[i & (xorlen-1)];
536 /* calculate checksum */
537 for (i=0; i<slen; i++)
538 crc += outbuf[i];
540 header[0] = header[2] = 'Z';
541 header[1] = header[3] = version;
542 int2le(length, &header[4]);
543 int2le(slen, &header[8]);
544 int2le(crc, &header[12]);
545 length = slen;
546 break;
549 #define MY_FIRMWARE_TYPE "Rockbox"
550 #define MY_HEADER_VERSION 1
551 default:
552 strncpy((char *)header, MY_FIRMWARE_TYPE,9);
553 header[9]='\0'; /*shouldn't have to, but to be SURE */
554 header[10]=MY_HEADER_VERSION&0xFF;
555 header[11]=(crc>>8)&0xFF;
556 header[12]=crc&0xFF;
557 int2be(sizeof(header), &header[12]);
558 break;
561 /* write file */
562 file = fopen(oname,"wb");
563 if ( !file ) {
564 perror(oname);
565 return -1;
567 if (headerlen > 0) {
568 if ( !fwrite(header,headerlen,1,file) ) {
569 perror(oname);
570 return -1;
573 if ( !fwrite(outbuf,length,1,file) ) {
574 perror(oname);
575 return -1;
577 fclose(file);
579 free(inbuf);
580 free(outbuf);
582 return 0;
585 int iaudio_encode(char *iname, char *oname, char *idstring)
587 size_t len;
588 int length;
589 FILE *file;
590 unsigned char *outbuf;
591 int i;
592 unsigned char sum = 0;
594 file = fopen(iname, "rb");
595 if (!file) {
596 perror(iname);
597 return -1;
599 fseek(file,0,SEEK_END);
600 length = ftell(file);
602 fseek(file,0,SEEK_SET);
603 outbuf = malloc(length+0x1030);
605 if ( !outbuf ) {
606 printf("out of memory!\n");
607 return -1;
610 len = fread(outbuf+0x1030, 1, length, file);
611 if(len < (size_t) length) {
612 perror(iname);
613 return -2;
616 memset(outbuf, 0, 0x1030);
617 strcpy((char *)outbuf, idstring);
618 memcpy(outbuf+0x20, iaudio_bl_flash,
619 BMPWIDTH_iaudio_bl_flash * (BMPHEIGHT_iaudio_bl_flash/8) * 2);
620 short2be(BMPWIDTH_iaudio_bl_flash, &outbuf[0x10]);
621 short2be((BMPHEIGHT_iaudio_bl_flash/8), &outbuf[0x12]);
622 outbuf[0x19] = 2;
624 for(i = 0; i < length;i++)
625 sum += outbuf[0x1030 + i];
627 int2be(length, &outbuf[0x1024]);
628 outbuf[0x102b] = sum;
630 fclose(file);
632 file = fopen(oname, "wb");
633 if (!file) {
634 perror(oname);
635 return -3;
638 len = fwrite(outbuf, 1, length+0x1030, file);
639 if(len < (size_t)length) {
640 perror(oname);
641 return -4;
644 fclose(file);
645 return 0;
649 /* Create an ipod firmware partition image
651 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
653 This function doesn't yet handle the Broadcom resource image for the 5g,
654 so the resulting images won't be usable.
656 This has also only been tested on an ipod Photo
659 int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc)
661 static const char *apple_stop_sign = "{{~~ /-----\\ "\
662 "{{~~ / \\ "\
663 "{{~~| | "\
664 "{{~~| S T O P | "\
665 "{{~~| | "\
666 "{{~~ \\ / "\
667 "{{~~ \\-----/ "\
668 "Copyright(C) 200"\
669 "1 Apple Computer"\
670 ", Inc.----------"\
671 "----------------"\
672 "----------------"\
673 "----------------"\
674 "----------------"\
675 "----------------"\
676 "---------------";
677 size_t len;
678 int length;
679 int rsrclength;
680 int rsrcoffset;
681 FILE *file;
682 unsigned int sum = 0;
683 unsigned int rsrcsum = 0;
684 unsigned char *outbuf;
685 int bufsize;
686 int i;
688 file = fopen(iname, "rb");
689 if (!file) {
690 perror(iname);
691 return -1;
693 fseek(file,0,SEEK_END);
694 length = ftell(file);
696 fseek(file,0,SEEK_SET);
698 bufsize=(length+0x4600);
699 if (fake_rsrc) {
700 bufsize = (bufsize + 0x400) & ~0x200;
703 outbuf = malloc(bufsize);
705 if ( !outbuf ) {
706 printf("out of memory!\n");
707 return -1;
710 len = fread(outbuf+0x4600, 1, length, file);
711 if(len < (size_t)length) {
712 perror(iname);
713 return -2;
715 fclose(file);
717 /* Calculate checksum for later use in header */
718 for(i = 0x4600; i < 0x4600+length;i++)
719 sum += outbuf[i];
721 /* Clear the header area to zero */
722 memset(outbuf, 0, 0x4600);
724 /* APPLE STOP SIGN */
725 strcpy((char *)outbuf, apple_stop_sign);
727 /* VOLUME HEADER */
728 memcpy(&outbuf[0x100],"]ih[",4); /* Magic */
729 int2le(0x4000, &outbuf[0x104]); /* Firmware offset relative to 0x200 */
730 short2le(0x10c, &outbuf[0x108]); /* Location of extended header */
731 short2le(fw_ver, &outbuf[0x10a]);
733 /* Firmware Directory - "osos" entry */
734 memcpy(&outbuf[0x4200],"!ATAsoso",8); /* dev and type */
735 int2le(0, &outbuf[0x4208]); /* id */
736 int2le(0x4400, &outbuf[0x420c]); /* devOffset */
737 int2le(length, &outbuf[0x4210]); /* Length of firmware */
738 int2le(0x10000000, &outbuf[0x4214]); /* Addr */
739 int2le(0, &outbuf[0x4218]); /* Entry Offset */
740 int2le(sum, &outbuf[0x421c]); /* Checksum */
741 int2le(0x00006012, &outbuf[0x4220]); /* vers - 0x6012 is a guess */
742 int2le(0xffffffff, &outbuf[0x4224]); /* LoadAddr - for flash images */
744 /* "rsrc" entry (if applicable) */
745 if (fake_rsrc) {
746 rsrcoffset=(length+0x4600+0x200) & ~0x200;
747 rsrclength=0x200;
748 rsrcsum=0;
750 memcpy(&outbuf[0x4228],"!ATAcrsr",8); /* dev and type */
751 int2le(0, &outbuf[0x4230]); /* id */
752 int2le(rsrcoffset, &outbuf[0x4234]); /* devOffset */
753 int2le(rsrclength, &outbuf[0x4238]); /* Length of firmware */
754 int2le(0x10000000, &outbuf[0x423c]); /* Addr */
755 int2le(0, &outbuf[0x4240]); /* Entry Offset */
756 int2le(rsrcsum, &outbuf[0x4244]); /* Checksum */
757 int2le(0x0000b000, &outbuf[0x4248]); /* vers */
758 int2le(0xffffffff, &outbuf[0x424c]); /* LoadAddr - for flash images */
761 file = fopen(oname, "wb");
762 if (!file) {
763 perror(oname);
764 return -3;
767 len = fwrite(outbuf, 1, length+0x4600, file);
768 if(len < (size_t)length) {
769 perror(oname);
770 return -4;
773 fclose(file);
775 return 0;