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 */
33 /* Descriptive name of these models */
34 static const char* model_names
[] = {
35 [MODEL_HD200
] = "MPIO HD200",
36 [MODEL_HD300
] = "MPIO HD300",
39 /* Model names used in the Rockbox header in ".mpio" files - these match the
40 -add parameter to the "scramble" tool */
41 static const char* rb_model_names
[] = {
42 [MODEL_HD200
] = "hd20",
43 [MODEL_HD300
] = "hd30",
46 /* Model numbers used to initialise the checksum in the Rockbox header in
47 ".mpio" files - these are the same as MODEL_NUMBER in config-target.h */
48 static const int rb_model_num
[] = {
53 /* Strings which indentify OF version */
54 static const char* of_model_string
[] = {
55 [MODEL_HD200
] = "HD200 HDD Audio Ver113005",
56 [MODEL_HD300
] = "HD300 HDD Audio Ver113006",
59 /* MPIO HD200 and HD300 firmware is plain binary image
60 * 4 bytes of initial SP (loaded on reset)
61 * 4 bytes of initial PC (loaded on reset)
62 * binary image with entry point 0x00000008
64 * We put our bootloader code at 0x000e0000
65 * and patch reset vector to jump directly
66 * into our code on reset
69 static unsigned char image
[OF_FIRMWARE_LEN
];
71 static unsigned int get_uint32be(unsigned char* p
)
73 return ((p
[0] << 24) | (p
[1] << 16) | (p
[2]<<8) | p
[3]);
76 static long checksum(unsigned char* buf
, int model
, unsigned long length
)
78 unsigned long chksum
= model
;
84 for (i
= 0; i
< length
; i
++)
92 int mkmpioboot(const char* infile
, const char* bootfile
, const char* outfile
, int origin
)
98 unsigned long file_checksum
;
99 unsigned char header
[8];
101 memset(image
, 0xff, sizeof(image
));
103 /* First, read the mpio original firmware into the image */
104 f
= fopen(infile
, "rb");
107 fprintf(stderr
, "[ERR] Can not open %s file for reading\n", infile
);
111 i
= fread(image
, 1, OF_FIRMWARE_LEN
, f
);
112 if(i
< OF_FIRMWARE_LEN
)
114 fprintf(stderr
, "[ERR] %s file read error\n", infile
);
121 /* Now check if we have OF file loaded based on presence
122 * of the version string in firmware
125 for(model_index
= 0; model_index
< NUM_MODELS
; model_index
++)
126 if (strcmp(of_model_string
[model_index
],
127 (char*)(image
+ MPIO_STRING_OFFSET
)) == 0)
130 if(model_index
== NUM_MODELS
)
132 fprintf(stderr
, "[ERR] Unknown MPIO original firmware version\n");
136 fprintf(stderr
, "[INFO] Loading original firmware file for %s\n",
137 model_names
[model_index
]);
139 /* Now, read the boot loader into the image */
140 f
= fopen(bootfile
, "rb");
143 fprintf(stderr
, "[ERR] Can not open %s file for reading\n", bootfile
);
147 fprintf(stderr
, "[INFO] Loading Rockbox bootloader file\n");
149 /* get bootloader size
152 fseek(f
, 0, SEEK_END
);
155 if (len
> BOOTLOADER_MAX_SIZE
)
157 fprintf(stderr
, "[ERR] Bootloader doesn't fit in firmware file.\n");
158 fprintf(stderr
, "[ERR] This bootloader is %d bytes long\n", len
);
159 fprintf(stderr
, "[ERR] and maximum allowed size is %d bytes\n",
160 BOOTLOADER_MAX_SIZE
);
164 /* Now check if the place we want to put
165 * our bootloader is free
169 if (image
[origin
+i
] != 0)
171 fprintf(stderr
, "[ERR] Place for bootloader in OF file not empty\n");
176 fseek(f
, 0, SEEK_SET
);
178 /* get bootloader header*/
181 if ( memcmp(header
+ 4, rb_model_names
[model_index
], 4) != 0 )
183 fprintf(stderr
, "[ERR] Original firmware and rockbox bootloader mismatch!\n");
184 fprintf(stderr
, "[ERR] Double check that you have bootloader for %s\n",
185 model_names
[model_index
]);
190 fseek(f
, 8, SEEK_SET
);
192 i
= fread(image
+ origin
, 1, len
, f
);
195 fprintf(stderr
, "[ERR] %s file read error\n", bootfile
);
202 /* calculate checksum and compare with data
205 file_checksum
= checksum(image
+ origin
, rb_model_num
[model_index
], len
);
207 if ( file_checksum
!= get_uint32be(header
) )
209 fprintf(stderr
,"[ERR] Bootloader checksum error\n");
213 f
= fopen(outfile
, "wb");
216 fprintf(stderr
, "[ERR] Can not open %s file for writing\n" ,outfile
);
220 fprintf(stderr
, "[INFO] Patching reset vector\n");
222 /* Patch the stack pointer address */
223 image
[0] = image
[origin
+ 0];
224 image
[1] = image
[origin
+ 1];
225 image
[2] = image
[origin
+ 2];
226 image
[3] = image
[origin
+ 3];
228 /* Patch the reset vector to start the boot loader */
229 image
[4] = image
[origin
+ 4];
230 image
[5] = image
[origin
+ 5];
231 image
[6] = image
[origin
+ 6];
232 image
[7] = image
[origin
+ 7];
234 i
= fwrite(image
, 1, OF_FIRMWARE_LEN
, f
);
235 if(i
< OF_FIRMWARE_LEN
)
237 fprintf(stderr
,"[ERR] %s file write error\n", outfile
);
242 fprintf(stderr
,"[INFO] Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN
, outfile
);
243 fprintf(stderr
,"[INFO] Patching succeeded!\n");