Add w32 mountpoint resolving based on disc number correctly this time.
[Rockbox.git] / tools / scramble.c
blobace8337a1baaf8100604a36533374441a3aa7f65
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include "iriver.h"
27 #include "gigabeat.h"
28 #include "gigabeats.h"
29 #include "mi4.h"
30 #include "telechips.h"
31 #include "creative.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);
37 enum
39 ARCHOS_PLAYER, /* and V1 recorder */
40 ARCHOS_V2RECORDER,
41 ARCHOS_FMRECORDER,
42 ARCHOS_ONDIO_SP,
43 ARCHOS_ONDIO_FM
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)
57 addr[0] = val & 0xFF;
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];
65 return res;
68 void int2le(unsigned int val, unsigned char* addr)
70 addr[0] = val & 0xFF;
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;
81 addr[3] = val & 0xFF;
84 void short2be(unsigned short val, unsigned char* addr)
86 addr[0] = (val >> 8) & 0xff;
87 addr[1] = val & 0xFF;
90 void usage(void)
92 printf("usage: scramble [options] <input file> <output file> [xor string]\n");
93 printf("options:\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"
110 "\t zenv, zen\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");
128 exit(1);
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;
141 int headerlen = 6;
142 FILE* file;
143 int version=0;
144 unsigned long modelnum;
145 char modelname[5];
146 int model_id;
147 enum { none, scramble, xor, tcc_sum, tcc_crc, add } method = scramble;
149 model_id = ARCHOS_PLAYER;
151 if (argc < 3) {
152 usage();
155 if(!strcmp(argv[1], "-fm")) {
156 headerlen = 24;
157 iname = argv[2];
158 oname = argv[3];
159 version = 4;
160 model_id = ARCHOS_FMRECORDER;
163 else if(!strcmp(argv[1], "-v2")) {
164 headerlen = 24;
165 iname = argv[2];
166 oname = argv[3];
167 version = 2;
168 model_id = ARCHOS_V2RECORDER;
171 else if(!strcmp(argv[1], "-ofm")) {
172 headerlen = 24;
173 iname = argv[2];
174 oname = argv[3];
175 version = 8;
176 model_id = ARCHOS_ONDIO_FM;
179 else if(!strcmp(argv[1], "-osp")) {
180 headerlen = 24;
181 iname = argv[2];
182 oname = argv[3];
183 version = 16;
184 model_id = ARCHOS_ONDIO_SP;
187 else if(!strcmp(argv[1], "-neo")) {
188 headerlen = 17;
189 iname = argv[2];
190 oname = argv[3];
191 method = none;
193 else if(!strncmp(argv[1], "-mm=", 4)) {
194 headerlen = 16;
195 iname = argv[2];
196 oname = argv[3];
197 method = xor;
198 version = argv[1][4];
199 if (argc > 4)
200 xorstring = argv[4];
201 else {
202 printf("Multimedia needs an xor string\n");
203 return -1;
206 else if(!strncmp(argv[1], "-tcc=", 4)) {
207 headerlen = 0;
208 iname = argv[2];
209 oname = argv[3];
211 if(!strcmp(&argv[1][5], "sum"))
212 method = tcc_sum;
213 else if(!strcmp(&argv[1][5], "crc"))
214 method = tcc_crc;
215 else {
216 fprintf(stderr, "unsupported TCC method: %s\n", &argv[1][5]);
217 return 2;
220 else if(!strncmp(argv[1], "-add=", 5)) {
221 iname = argv[2];
222 oname = argv[3];
223 method = add;
225 if(!strcmp(&argv[1][5], "h120"))
226 modelnum = 0;
227 else if(!strcmp(&argv[1][5], "h140"))
228 modelnum = 0; /* the same as the h120 */
229 else if(!strcmp(&argv[1][5], "h100"))
230 modelnum = 1;
231 else if(!strcmp(&argv[1][5], "h300"))
232 modelnum = 2;
233 else if(!strcmp(&argv[1][5], "ipco"))
234 modelnum = 3;
235 else if(!strcmp(&argv[1][5], "nano"))
236 modelnum = 4;
237 else if(!strcmp(&argv[1][5], "ipvd"))
238 modelnum = 5;
239 else if(!strcmp(&argv[1][5], "fp7x"))
240 modelnum = 6;
241 else if(!strcmp(&argv[1][5], "ip3g"))
242 modelnum = 7;
243 else if(!strcmp(&argv[1][5], "ip4g"))
244 modelnum = 8;
245 else if(!strcmp(&argv[1][5], "mini"))
246 modelnum = 9;
247 else if(!strcmp(&argv[1][5], "iax5"))
248 modelnum = 10;
249 else if(!strcmp(&argv[1][5], "mn2g"))
250 modelnum = 11;
251 else if(!strcmp(&argv[1][5], "h10"))
252 modelnum = 13;
253 else if(!strcmp(&argv[1][5], "h10_5gb"))
254 modelnum = 14;
255 else if(!strcmp(&argv[1][5], "tpj2"))
256 modelnum = 15;
257 else if(!strcmp(&argv[1][5], "e200"))
258 modelnum = 16;
259 else if(!strcmp(&argv[1][5], "iam5"))
260 modelnum = 17;
261 else if(!strcmp(&argv[1][5], "giga"))
262 modelnum = 18;
263 else if(!strcmp(&argv[1][5], "1g2g"))
264 modelnum = 19;
265 else if(!strcmp(&argv[1][5], "c200"))
266 modelnum = 20;
267 else if(!strcmp(&argv[1][5], "gigs"))
268 modelnum = 21;
269 else if(!strcmp(&argv[1][5], "m500"))
270 modelnum = 22;
271 else if(!strcmp(&argv[1][5], "m100"))
272 modelnum = 23;
273 else if(!strcmp(&argv[1][5], "d2"))
274 modelnum = 24;
275 else if(!strcmp(&argv[1][5], "iam3"))
276 modelnum = 25;
277 else if(!strcmp(&argv[1][5], "9200")) /* Philips SA9200 */
278 modelnum = 26;
279 else if(!strcmp(&argv[1][5], "1630")) /* Philips HDD1630 */
280 modelnum = 31;
281 else {
282 fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
283 return 2;
285 /* we store a 4-letter model name too, for humans */
286 strcpy(modelname, &argv[1][5]);
287 chksum = modelnum; /* start checksum calcs with this */
290 else if(!strcmp(argv[1], "-iriver")) {
291 /* iRiver code dealt with in the iriver.c code */
292 iname = argv[2];
293 oname = argv[3];
294 return (iriver_encode(iname, oname, FALSE) != 0) ? -1 : 0;
296 else if(!strcmp(argv[1], "-gigabeat")) {
297 /* iRiver code dealt with in the iriver.c code */
298 iname = argv[2];
299 oname = argv[3];
300 gigabeat_code(iname, oname);
301 return 0;
303 else if(!strcmp(argv[1], "-gigabeats")) {
304 iname = argv[2];
305 oname = argv[3];
306 gigabeat_s_code(iname, oname);
307 return 0;
309 else if(!strcmp(argv[1], "-iaudiox5")) {
310 iname = argv[2];
311 oname = argv[3];
312 return iaudio_encode(iname, oname, "COWON_X5_FW");
314 else if(!strcmp(argv[1], "-iaudiox5v")) {
315 iname = argv[2];
316 oname = argv[3];
317 return iaudio_encode(iname, oname, "COWON_X5V_FW");
319 else if(!strcmp(argv[1], "-iaudiom5")) {
320 iname = argv[2];
321 oname = argv[3];
322 return iaudio_encode(iname, oname, "COWON_M5_FW");
324 else if(!strcmp(argv[1], "-iaudiom3")) {
325 iname = argv[2];
326 oname = argv[3];
327 return iaudio_encode(iname, oname, "COWON_M3_FW");
329 else if(!strcmp(argv[1], "-ipod3g")) {
330 iname = argv[2];
331 oname = argv[3];
332 return ipod_encode(iname, oname, 2, false); /* Firmware image v2 */
334 else if(!strcmp(argv[1], "-ipod4g")) {
335 iname = argv[2];
336 oname = argv[3];
337 return ipod_encode(iname, oname, 3, false); /* Firmware image v3 */
339 else if(!strcmp(argv[1], "-ipod5g")) {
340 iname = argv[2];
341 oname = argv[3];
342 return ipod_encode(iname, oname, 3, true); /* Firmware image v3 */
344 else if(!strncmp(argv[1], "-creative=", 10)) {
345 iname = argv[2];
346 oname = argv[3];
347 if(!strcmp(&argv[1][10], "zvm"))
348 return zvm_encode(iname, oname, ZENVISIONM);
349 else if(!strcmp(&argv[1][10], "zvm60"))
350 return zvm_encode(iname, oname, ZENVISIONM60);
351 else if(!strcmp(&argv[1][10], "zenvision"))
352 return zvm_encode(iname, oname, ZENVISION);
353 else if(!strcmp(&argv[1][10], "zenv"))
354 return zvm_encode(iname, oname, ZENV);
355 else if(!strcmp(&argv[1][10], "zen"))
356 return zvm_encode(iname, oname, ZEN);
357 else {
358 fprintf(stderr, "unsupported Creative device: %s\n", &argv[1][10]);
359 return 2;
362 else if(!strncmp(argv[1], "-mi4", 4)) {
363 int mi4magic;
364 char model[4] = "";
365 char type[4] = "";
367 if(!strcmp(&argv[1][4], "v2")) {
368 mi4magic = MI4_MAGIC_DEFAULT;
369 version = 0x00010201;
371 else if(!strcmp(&argv[1][4], "v3")) {
372 mi4magic = MI4_MAGIC_DEFAULT;
373 version = 0x00010301;
375 else if(!strcmp(&argv[1][4], "r")) {
376 mi4magic = MI4_MAGIC_R;
377 version = 0x00010301;
379 else {
380 printf( "Invalid mi4 version: %s\n", &argv[1][4]);
381 return -1;
384 iname = argv[2];
385 oname = argv[3];
387 if(!strncmp(argv[2], "-model=", 7)) {
388 iname = argv[3];
389 oname = argv[4];
390 strncpy(model, &argv[2][7], 4);
392 if(!strncmp(argv[3], "-type=", 6)) {
393 iname = argv[4];
394 oname = argv[5];
395 strncpy(type, &argv[3][6], 4);
399 return mi4_encode(iname, oname, version, mi4magic, model, type);
402 /* open file */
403 file = fopen(iname,"rb");
404 if (!file) {
405 perror(iname);
406 return -1;
408 fseek(file,0,SEEK_END);
409 length = ftell(file);
410 length = (length + 3) & ~3; /* Round up to nearest 4 byte boundary */
412 if ((method == scramble) &&
413 ((length + headerlen) >= size_limit[model_id])) {
414 printf("error: firmware image is %ld bytes while max size is %u!\n",
415 length + headerlen,
416 size_limit[model_id]);
417 fclose(file);
418 return -1;
421 fseek(file,0,SEEK_SET);
422 inbuf = malloc(length);
423 if (method == xor)
424 outbuf = malloc(length*2);
425 else if(method == add)
426 outbuf = malloc(length + 8);
427 else
428 outbuf = malloc(length);
429 if ( !inbuf || !outbuf ) {
430 printf("out of memory!\n");
431 return -1;
433 if(length> 4) {
434 /* zero-fill the last 4 bytes to make sure there's no rubbish there
435 when we write the size-aligned file later */
436 memset(outbuf+length-4, 0, 4);
439 /* read file */
440 i=fread(inbuf,1,length,file);
441 if ( !i ) {
442 perror(iname);
443 return -1;
445 fclose(file);
447 switch (method)
449 case add:
450 for (i = 0; i < length; i++) {
451 /* add 8 unsigned bits but keep a 32 bit sum */
452 chksum += inbuf[i];
454 break;
455 case scramble:
456 slen = length/4;
457 for (i = 0; i < length; i++) {
458 unsigned long addr = (i >> 2) + ((i % 4) * slen);
459 unsigned char data = inbuf[i];
460 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
461 outbuf[addr] = data;
463 break;
465 case xor:
466 /* "compress" */
467 slen = 0;
468 for (i=0; i<length; i++) {
469 if (!(i&7))
470 outbuf[slen++] = 0xff; /* all data is uncompressed */
471 outbuf[slen++] = inbuf[i];
473 break;
474 case none:
475 default:
476 /* dummy case just to silence picky compilers */
477 break;
480 if((method == none) || (method == scramble) || (method == xor)) {
481 /* calculate checksum */
482 for (i=0;i<length;i++)
483 crc += inbuf[i];
486 memset(header, 0, sizeof header);
487 switch (method)
489 case add:
491 int2be(chksum, header); /* checksum, big-endian */
492 memcpy(&header[4], modelname, 4); /* 4 bytes model name */
493 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
494 headerlen = 8;
496 break;
498 case tcc_sum:
499 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
500 telechips_encode_sum(outbuf, length);
501 break;
503 case tcc_crc:
504 memcpy(outbuf, inbuf, length); /* the input buffer to output*/
505 telechips_encode_crc(outbuf, length);
506 break;
508 case scramble:
509 if (headerlen == 6) {
510 int2be(length, header);
511 header[4] = (crc >> 8) & 0xff;
512 header[5] = crc & 0xff;
514 else {
515 header[0] =
516 header[1] =
517 header[2] =
518 header[3] = 0xff; /* ??? */
520 header[6] = (crc >> 8) & 0xff;
521 header[7] = crc & 0xff;
523 header[11] = version;
525 header[15] = headerlen; /* really? */
527 int2be(length, &header[20]);
529 break;
531 case xor:
533 int xorlen = strlen(xorstring);
535 /* xor data */
536 for (i=0; i<slen; i++)
537 outbuf[i] ^= xorstring[i & (xorlen-1)];
539 /* calculate checksum */
540 for (i=0; i<slen; i++)
541 crc += outbuf[i];
543 header[0] = header[2] = 'Z';
544 header[1] = header[3] = version;
545 int2le(length, &header[4]);
546 int2le(slen, &header[8]);
547 int2le(crc, &header[12]);
548 length = slen;
549 break;
552 #define MY_FIRMWARE_TYPE "Rockbox"
553 #define MY_HEADER_VERSION 1
554 default:
555 strncpy((char *)header, MY_FIRMWARE_TYPE,9);
556 header[9]='\0'; /*shouldn't have to, but to be SURE */
557 header[10]=MY_HEADER_VERSION&0xFF;
558 header[11]=(crc>>8)&0xFF;
559 header[12]=crc&0xFF;
560 int2be(sizeof(header), &header[12]);
561 break;
564 /* write file */
565 file = fopen(oname,"wb");
566 if ( !file ) {
567 perror(oname);
568 return -1;
570 if (headerlen > 0) {
571 if ( !fwrite(header,headerlen,1,file) ) {
572 perror(oname);
573 return -1;
576 if ( !fwrite(outbuf,length,1,file) ) {
577 perror(oname);
578 return -1;
580 fclose(file);
582 free(inbuf);
583 free(outbuf);
585 return 0;
588 int iaudio_encode(char *iname, char *oname, char *idstring)
590 size_t len;
591 int length;
592 FILE *file;
593 unsigned char *outbuf;
594 int i;
595 unsigned char sum = 0;
597 file = fopen(iname, "rb");
598 if (!file) {
599 perror(iname);
600 return -1;
602 fseek(file,0,SEEK_END);
603 length = ftell(file);
605 fseek(file,0,SEEK_SET);
606 outbuf = malloc(length+0x1030);
608 if ( !outbuf ) {
609 printf("out of memory!\n");
610 return -1;
613 len = fread(outbuf+0x1030, 1, length, file);
614 if(len < (size_t) length) {
615 perror(iname);
616 return -2;
619 memset(outbuf, 0, 0x1030);
620 strcpy((char *)outbuf, idstring);
621 memcpy(outbuf+0x20, iaudio_bl_flash,
622 BMPWIDTH_iaudio_bl_flash * (BMPHEIGHT_iaudio_bl_flash/8) * 2);
623 short2be(BMPWIDTH_iaudio_bl_flash, &outbuf[0x10]);
624 short2be((BMPHEIGHT_iaudio_bl_flash/8), &outbuf[0x12]);
625 outbuf[0x19] = 2;
627 for(i = 0; i < length;i++)
628 sum += outbuf[0x1030 + i];
630 int2be(length, &outbuf[0x1024]);
631 outbuf[0x102b] = sum;
633 fclose(file);
635 file = fopen(oname, "wb");
636 if (!file) {
637 perror(oname);
638 return -3;
641 len = fwrite(outbuf, 1, length+0x1030, file);
642 if(len < (size_t)length) {
643 perror(oname);
644 return -4;
647 fclose(file);
648 return 0;
652 /* Create an ipod firmware partition image
654 fw_ver = 2 for 3rd Gen ipods, 3 for all later ipods including 5g.
656 This function doesn't yet handle the Broadcom resource image for the 5g,
657 so the resulting images won't be usable.
659 This has also only been tested on an ipod Photo
662 int ipod_encode(char *iname, char *oname, int fw_ver, bool fake_rsrc)
664 static const char *apple_stop_sign = "{{~~ /-----\\ "\
665 "{{~~ / \\ "\
666 "{{~~| | "\
667 "{{~~| S T O P | "\
668 "{{~~| | "\
669 "{{~~ \\ / "\
670 "{{~~ \\-----/ "\
671 "Copyright(C) 200"\
672 "1 Apple Computer"\
673 ", Inc.----------"\
674 "----------------"\
675 "----------------"\
676 "----------------"\
677 "----------------"\
678 "----------------"\
679 "---------------";
680 size_t len;
681 int length;
682 int rsrclength;
683 int rsrcoffset;
684 FILE *file;
685 unsigned int sum = 0;
686 unsigned int rsrcsum = 0;
687 unsigned char *outbuf;
688 int bufsize;
689 int i;
691 file = fopen(iname, "rb");
692 if (!file) {
693 perror(iname);
694 return -1;
696 fseek(file,0,SEEK_END);
697 length = ftell(file);
699 fseek(file,0,SEEK_SET);
701 bufsize=(length+0x4600);
702 if (fake_rsrc) {
703 bufsize = (bufsize + 0x400) & ~0x200;
706 outbuf = malloc(bufsize);
708 if ( !outbuf ) {
709 printf("out of memory!\n");
710 return -1;
713 len = fread(outbuf+0x4600, 1, length, file);
714 if(len < (size_t)length) {
715 perror(iname);
716 return -2;
718 fclose(file);
720 /* Calculate checksum for later use in header */
721 for(i = 0x4600; i < 0x4600+length;i++)
722 sum += outbuf[i];
724 /* Clear the header area to zero */
725 memset(outbuf, 0, 0x4600);
727 /* APPLE STOP SIGN */
728 strcpy((char *)outbuf, apple_stop_sign);
730 /* VOLUME HEADER */
731 memcpy(&outbuf[0x100],"]ih[",4); /* Magic */
732 int2le(0x4000, &outbuf[0x104]); /* Firmware offset relative to 0x200 */
733 short2le(0x10c, &outbuf[0x108]); /* Location of extended header */
734 short2le(fw_ver, &outbuf[0x10a]);
736 /* Firmware Directory - "osos" entry */
737 memcpy(&outbuf[0x4200],"!ATAsoso",8); /* dev and type */
738 int2le(0, &outbuf[0x4208]); /* id */
739 int2le(0x4400, &outbuf[0x420c]); /* devOffset */
740 int2le(length, &outbuf[0x4210]); /* Length of firmware */
741 int2le(0x10000000, &outbuf[0x4214]); /* Addr */
742 int2le(0, &outbuf[0x4218]); /* Entry Offset */
743 int2le(sum, &outbuf[0x421c]); /* Checksum */
744 int2le(0x00006012, &outbuf[0x4220]); /* vers - 0x6012 is a guess */
745 int2le(0xffffffff, &outbuf[0x4224]); /* LoadAddr - for flash images */
747 /* "rsrc" entry (if applicable) */
748 if (fake_rsrc) {
749 rsrcoffset=(length+0x4600+0x200) & ~0x200;
750 rsrclength=0x200;
751 rsrcsum=0;
753 memcpy(&outbuf[0x4228],"!ATAcrsr",8); /* dev and type */
754 int2le(0, &outbuf[0x4230]); /* id */
755 int2le(rsrcoffset, &outbuf[0x4234]); /* devOffset */
756 int2le(rsrclength, &outbuf[0x4238]); /* Length of firmware */
757 int2le(0x10000000, &outbuf[0x423c]); /* Addr */
758 int2le(0, &outbuf[0x4240]); /* Entry Offset */
759 int2le(rsrcsum, &outbuf[0x4244]); /* Checksum */
760 int2le(0x0000b000, &outbuf[0x4248]); /* vers */
761 int2le(0xffffffff, &outbuf[0x424c]); /* LoadAddr - for flash images */
764 file = fopen(oname, "wb");
765 if (!file) {
766 perror(oname);
767 return -3;
770 len = fwrite(outbuf, 1, length+0x4600, file);
771 if(len < (size_t)length) {
772 perror(oname);
773 return -4;
776 fclose(file);
778 return 0;