Fix r29171 red. Forgot to replace a few.
[kugel-rb.git] / rbutil / mkmpioboot / mkmpioboot.c
blobb36f009730e97978619538b8ce3b73df7a247ee6
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:$
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 ****************************************************************************/
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
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[] = {
49 [MODEL_HD200] = 69,
50 [MODEL_HD300] = 70,
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;
79 unsigned long i;
81 if(buf == NULL)
82 return -1;
84 for (i = 0; i < length; i++)
86 chksum += *buf++;
89 return chksum;
92 int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin)
94 FILE *f;
95 int i;
96 int len;
97 int model_index;
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");
105 if(!f)
107 fprintf(stderr, "[ERR] Can not open %s file for reading\n", infile);
108 return -1;
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);
115 fclose(f);
116 return -2;
119 fclose(f);
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)
128 break;
130 if(model_index == NUM_MODELS)
132 fprintf(stderr, "[ERR] Unknown MPIO original firmware version\n");
133 return -3;
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");
141 if(!f)
143 fprintf(stderr, "[ERR] Can not open %s file for reading\n", bootfile);
144 return -4;
147 fprintf(stderr, "[INFO] Loading Rockbox bootloader file\n");
149 /* get bootloader size
150 * excluding header
152 fseek(f, 0, SEEK_END);
153 len = ftell(f) - 8;
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);
161 return -5;
164 /* Now check if the place we want to put
165 * our bootloader is free
167 for(i=0;i<len;i++)
169 if (image[origin+i] != 0)
171 fprintf(stderr, "[ERR] Place for bootloader in OF file not empty\n");
172 return -6;
176 fseek(f, 0, SEEK_SET);
178 /* get bootloader header*/
179 fread(header,1,8,f);
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]);
186 return -7;
189 /* omit header */
190 fseek(f, 8, SEEK_SET);
192 i = fread(image + origin, 1, len, f);
193 if(i < len)
195 fprintf(stderr, "[ERR] %s file read error\n", bootfile);
196 fclose(f);
197 return -8;
200 fclose(f);
202 /* calculate checksum and compare with data
203 * from header
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");
210 return -9;
213 f = fopen(outfile, "wb");
214 if(!f)
216 fprintf(stderr, "[ERR] Can not open %s file for writing\n" ,outfile);
217 return -10;
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);
238 fclose(f);
239 return -11;
242 fprintf(stderr,"[INFO] Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN, outfile);
243 fprintf(stderr,"[INFO] Patching succeeded!\n");
245 fclose(f);
247 return 0;