1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 by Marcin Bukat
12 * code taken mostly from mkboot.c
13 * Copyright (C) 2005 by Linus Nielsen Feltzing
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
23 ****************************************************************************/
27 #include "mkmpioboot.h"
29 #define OF_FIRMWARE_LEN 0x100000 /* size of the OF file */
30 #define MPIO_STRING_OFFSET 0xfffe0 /* offset of the version string in OF */
31 #define BOOTLOADER_MAX_SIZE 0x1f800 /* free space size */
34 /* Descriptive name of this model */
35 const char* model_name
;
36 /* Model name used in the Rockbox header in ".mpio" files - these match the
37 -add parameter to the "scramble" tool */
38 const char* rb_model_name
;
39 /* Model number used to initialise the checksum in the Rockbox header in
40 ".mpio" files - these are the same as MODEL_NUMBER in config-target.h */
41 const int rb_model_num
;
42 /* Strings which indentifies OF version */
43 const char* of_model_string
;
46 static const struct mpio_model mpio_models
[] = {
48 { "MPIO HD200", "hd20", 69, "HD200 HDD Audio Ver113005" },
50 { "MPIO HD300", "hd30", 70, "HD300 HDD Audio Ver113006" },
54 /* MPIO HD200 and HD300 firmware is plain binary image
55 * 4 bytes of initial SP (loaded on reset)
56 * 4 bytes of initial PC (loaded on reset)
57 * binary image with entry point 0x00000008
59 * We put our bootloader code at 0x000e0000
60 * and patch reset vector to jump directly
61 * into our code on reset
64 static unsigned char image
[OF_FIRMWARE_LEN
];
66 static unsigned int get_uint32be(unsigned char* p
)
68 return ((p
[0] << 24) | (p
[1] << 16) | (p
[2]<<8) | p
[3]);
71 static long checksum(unsigned char* buf
, int model
, unsigned long length
)
73 unsigned long chksum
= model
;
79 for (i
= 0; i
< length
; i
++)
87 int mkmpioboot(const char* infile
, const char* bootfile
, const char* outfile
, int origin
)
93 unsigned long file_checksum
;
94 unsigned char header
[8];
96 memset(image
, 0xff, sizeof(image
));
98 /* First, read the mpio original firmware into the image */
99 f
= fopen(infile
, "rb");
102 fprintf(stderr
, "[ERR] Can not open %s file for reading\n", infile
);
106 i
= fread(image
, 1, OF_FIRMWARE_LEN
, f
);
107 if(i
< OF_FIRMWARE_LEN
)
109 fprintf(stderr
, "[ERR] %s file read error\n", infile
);
116 /* Now check if we have OF file loaded based on presence
117 * of the version string in firmware
120 for(model_index
= 0; model_index
< NUM_MODELS
; model_index
++)
121 if (strcmp(mpio_models
[model_index
].of_model_string
,
122 (char*)(image
+ MPIO_STRING_OFFSET
)) == 0)
125 if(model_index
== NUM_MODELS
)
127 fprintf(stderr
, "[ERR] Unknown MPIO original firmware version\n");
131 fprintf(stderr
, "[INFO] Loading original firmware file for %s\n",
132 mpio_models
[model_index
].model_name
);
134 /* Now, read the boot loader into the image */
135 f
= fopen(bootfile
, "rb");
138 fprintf(stderr
, "[ERR] Can not open %s file for reading\n", bootfile
);
142 fprintf(stderr
, "[INFO] Loading Rockbox bootloader file\n");
144 /* get bootloader size
147 fseek(f
, 0, SEEK_END
);
150 if (len
> BOOTLOADER_MAX_SIZE
)
152 fprintf(stderr
, "[ERR] Bootloader doesn't fit in firmware file.\n");
153 fprintf(stderr
, "[ERR] This bootloader is %d bytes long\n", len
);
154 fprintf(stderr
, "[ERR] and maximum allowed size is %d bytes\n",
155 BOOTLOADER_MAX_SIZE
);
159 /* Now check if the place we want to put
160 * our bootloader is free
164 if (image
[origin
+i
] != 0)
166 fprintf(stderr
, "[ERR] Place for bootloader in OF file not empty\n");
171 fseek(f
, 0, SEEK_SET
);
173 /* get bootloader header*/
176 if ( memcmp(header
+ 4, mpio_models
[model_index
].rb_model_name
, 4) != 0 )
178 fprintf(stderr
, "[ERR] Original firmware and rockbox bootloader mismatch!\n");
179 fprintf(stderr
, "[ERR] Double check that you have bootloader for %s\n",
180 mpio_models
[model_index
].model_name
);
185 fseek(f
, 8, SEEK_SET
);
187 i
= fread(image
+ origin
, 1, len
, f
);
190 fprintf(stderr
, "[ERR] %s file read error\n", bootfile
);
197 /* calculate checksum and compare with data
200 file_checksum
= checksum(image
+ origin
, mpio_models
[model_index
].rb_model_num
, len
);
202 if ( file_checksum
!= get_uint32be(header
) )
204 fprintf(stderr
,"[ERR] Bootloader checksum error\n");
208 f
= fopen(outfile
, "wb");
211 fprintf(stderr
, "[ERR] Can not open %s file for writing\n" ,outfile
);
215 fprintf(stderr
, "[INFO] Patching reset vector\n");
217 /* Patch the stack pointer address */
218 image
[0] = image
[origin
+ 0];
219 image
[1] = image
[origin
+ 1];
220 image
[2] = image
[origin
+ 2];
221 image
[3] = image
[origin
+ 3];
223 /* Patch the reset vector to start the boot loader */
224 image
[4] = image
[origin
+ 4];
225 image
[5] = image
[origin
+ 5];
226 image
[6] = image
[origin
+ 6];
227 image
[7] = image
[origin
+ 7];
229 i
= fwrite(image
, 1, OF_FIRMWARE_LEN
, f
);
230 if(i
< OF_FIRMWARE_LEN
)
232 fprintf(stderr
,"[ERR] %s file write error\n", outfile
);
237 fprintf(stderr
,"[INFO] Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN
, outfile
);
238 fprintf(stderr
,"[INFO] Patching succeeded!\n");