summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rbutil/mkmpioboot/main.c8
-rw-r--r--rbutil/mkmpioboot/mkmpioboot.c136
-rw-r--r--rbutil/mkmpioboot/mkmpioboot.h9
3 files changed, 114 insertions, 39 deletions
diff --git a/rbutil/mkmpioboot/main.c b/rbutil/mkmpioboot/main.c
index 38e6d25288..9861cba261 100644
--- a/rbutil/mkmpioboot/main.c
+++ b/rbutil/mkmpioboot/main.c
@@ -37,7 +37,13 @@ int main(int argc, char *argv[])
37 char *infile, *bootfile, *outfile; 37 char *infile, *bootfile, *outfile;
38 int origin = 0xe0000; /* MPIO HD200 bootloader address */ 38 int origin = 0xe0000; /* MPIO HD200 bootloader address */
39 39
40 if(argc < 3) { 40 fprintf(stderr,
41"mkmpioboot Version " VERSION "\n"
42"This is free software; see the source for copying conditions. There is NO\n"
43"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
44"\n");
45
46 if(argc < 3) {
41 usage(); 47 usage();
42 } 48 }
43 49
diff --git a/rbutil/mkmpioboot/mkmpioboot.c b/rbutil/mkmpioboot/mkmpioboot.c
index 6d52e53f09..37dac60ec8 100644
--- a/rbutil/mkmpioboot/mkmpioboot.c
+++ b/rbutil/mkmpioboot/mkmpioboot.c
@@ -26,13 +26,37 @@
26#include <string.h> 26#include <string.h>
27#include "mkmpioboot.h" 27#include "mkmpioboot.h"
28 28
29#define OF_FIRMWARE_LEN 0x100000 /* size of HD200_UPG.SYS file */ 29#define OF_FIRMWARE_LEN 0x100000 /* size of the OF file */
30#define MPIO_STRING_OFFSET 0xfffe0 30#define MPIO_STRING_OFFSET 0xfffe0 /* offset of the version string in OF */
31 31#define BOOTLOADER_MAX_SIZE 0x1f800 /* free space size */
32/* We support only 1.30.05 version of OF for now */ 32
33static char *mpio_string = "HD200 HDD Audio Ver113005"; 33/* Descriptive name of these models */
34 34const char* model_names[] = {
35/* MPIO HD200 firmware is plain binary image 35 [MODEL_HD200] = "MPIO HD200",
36 [MODEL_HD300] = "MPIO HD300",
37};
38
39/* Model names used in the Rockbox header in ".mpio" files - these match the
40 -add parameter to the "scramble" tool */
41static const char* rb_model_names[] = {
42 [MODEL_HD200] = "hd20",
43 [MODEL_HD300] = "hd30",
44};
45
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 */
48static const int rb_model_num[] = {
49 [MODEL_HD200] = 69,
50 [MODEL_HD300] = 70,
51};
52
53/* Strings which indentify OF version */
54static const char* of_model_string[] = {
55 [MODEL_HD200] = "HD200 HDD Audio Ver113005",
56 [MODEL_HD300] = "HD300 HDD Audio Ver113006",
57};
58
59/* MPIO HD200 and HD300 firmware is plain binary image
36 * 4 bytes of initial SP (loaded on reset) 60 * 4 bytes of initial SP (loaded on reset)
37 * 4 bytes of initial PC (loaded on reset) 61 * 4 bytes of initial PC (loaded on reset)
38 * binary image with entry point 0x00000008 62 * binary image with entry point 0x00000008
@@ -49,9 +73,9 @@ static unsigned int get_uint32be(unsigned char* p)
49 return ((p[0] << 24) | (p[1] << 16) | (p[2]<<8) | p[3]); 73 return ((p[0] << 24) | (p[1] << 16) | (p[2]<<8) | p[3]);
50} 74}
51 75
52static long checksum(unsigned char* buf, unsigned long length) 76static long checksum(unsigned char* buf, int model, unsigned long length)
53{ 77{
54 unsigned long chksum = 69; /* MPIO HD200 model number */ 78 unsigned long chksum = model;
55 unsigned long i; 79 unsigned long i;
56 80
57 if(buf == NULL) 81 if(buf == NULL)
@@ -70,21 +94,24 @@ int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, in
70 FILE *f; 94 FILE *f;
71 int i; 95 int i;
72 int len; 96 int len;
97 int model_index;
73 unsigned long file_checksum; 98 unsigned long file_checksum;
74 unsigned char header_checksum[4]; 99 unsigned char header[8];
75 100
76 memset(image, 0xff, sizeof(image)); 101 memset(image, 0xff, sizeof(image));
77 102
78 /* First, read the mpio original firmware into the image */ 103 /* First, read the mpio original firmware into the image */
79 f = fopen(infile, "rb"); 104 f = fopen(infile, "rb");
80 if(!f) { 105 if(!f)
81 perror(infile); 106 {
107 fprintf(stderr, "[ERR] Can not open %s file for reading\n", infile);
82 return -1; 108 return -1;
83 } 109 }
84 110
85 i = fread(image, 1, OF_FIRMWARE_LEN, f); 111 i = fread(image, 1, OF_FIRMWARE_LEN, f);
86 if(i < OF_FIRMWARE_LEN) { 112 if(i < OF_FIRMWARE_LEN)
87 perror(infile); 113 {
114 fprintf(stderr, "[ERR] %s file read error\n", infile);
88 fclose(f); 115 fclose(f);
89 return -2; 116 return -2;
90 } 117 }
@@ -95,26 +122,45 @@ int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, in
95 * of the version string in firmware 122 * of the version string in firmware
96 */ 123 */
97 124
98 if (strcmp((char*)(image + MPIO_STRING_OFFSET),mpio_string) != 0) 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;
129
130 if(model_index == NUM_MODELS)
99 { 131 {
100 perror("Loaded firmware file does not look like MPIO OF file!"); 132 fprintf(stderr, "[ERR] Unknown MPIO original firmware version\n");
101 return -3; 133 return -3;
102 } 134 }
103 135
136 fprintf(stderr, "[INFO] Loading original firmware file for %s\n",
137 model_names[model_index]);
138
104 /* Now, read the boot loader into the image */ 139 /* Now, read the boot loader into the image */
105 f = fopen(bootfile, "rb"); 140 f = fopen(bootfile, "rb");
106 if(!f) { 141 if(!f)
107 perror(bootfile); 142 {
108 fclose(f); 143 fprintf(stderr, "[ERR] Can not open %s file for reading\n", bootfile);
109 return -4; 144 return -4;
110 } 145 }
111 146
147 fprintf(stderr, "[INFO] Loading Rockbox bootloader file\n");
148
112 /* get bootloader size 149 /* get bootloader size
113 * excluding header 150 * excluding header
114 */ 151 */
115 fseek(f, 0, SEEK_END); 152 fseek(f, 0, SEEK_END);
116 len = ftell(f) - 8; 153 len = ftell(f) - 8;
117 154
155 if (len > BOOTLOADER_MAX_SIZE)
156 {
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;
162 }
163
118 /* Now check if the place we want to put 164 /* Now check if the place we want to put
119 * our bootloader is free 165 * our bootloader is free
120 */ 166 */
@@ -122,24 +168,33 @@ int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, in
122 { 168 {
123 if (image[origin+i] != 0) 169 if (image[origin+i] != 0)
124 { 170 {
125 perror("Place for bootloader in OF file not empty"); 171 fprintf(stderr, "[ERR] Place for bootloader in OF file not empty\n");
126 return -5; 172 return -6;
127 } 173 }
128 } 174 }
129 175
130 fseek(f, 0, SEEK_SET); 176 fseek(f, 0, SEEK_SET);
131 177
132 /* get bootloader checksum from the header*/ 178 /* get bootloader header*/
133 fread(header_checksum,1,4,f); 179 fread(header,1,8,f);
180
181 if ( memcmp(header + 4, rb_model_names[model_index], 4) != 0 )
182 {
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;
187 }
134 188
135 /* omit header */ 189 /* omit header */
136 fseek(f, 8, SEEK_SET); 190 fseek(f, 8, SEEK_SET);
137 191
138 i = fread(image + origin, 1, len, f); 192 i = fread(image + origin, 1, len, f);
139 if(i < len) { 193 if(i < len)
140 perror(bootfile); 194 {
195 fprintf(stderr, "[ERR] %s file read error\n", bootfile);
141 fclose(f); 196 fclose(f);
142 return -6; 197 return -8;
143 } 198 }
144 199
145 fclose(f); 200 fclose(f);
@@ -147,20 +202,23 @@ int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, in
147 /* calculate checksum and compare with data 202 /* calculate checksum and compare with data
148 * from header 203 * from header
149 */ 204 */
150 file_checksum = checksum(image + origin, len); 205 file_checksum = checksum(image + origin, rb_model_num[model_index], len);
151 206
152 if ( file_checksum != get_uint32be(header_checksum) ) 207 if ( file_checksum != get_uint32be(header) )
153 { 208 {
154 printf("Bootloader checksum error\n"); 209 fprintf(stderr,"[ERR] Bootloader checksum error\n");
155 return -7; 210 return -9;
156 } 211 }
157 212
158 f = fopen(outfile, "wb"); 213 f = fopen(outfile, "wb");
159 if(!f) { 214 if(!f)
160 perror(outfile); 215 {
161 return -8; 216 fprintf(stderr, "[ERR] Can not open %s file for writing\n" ,outfile);
217 return -10;
162 } 218 }
163 219
220 fprintf(stderr, "[INFO] Patching reset vector\n");
221
164 /* Patch the stack pointer address */ 222 /* Patch the stack pointer address */
165 image[0] = image[origin + 0]; 223 image[0] = image[origin + 0];
166 image[1] = image[origin + 1]; 224 image[1] = image[origin + 1];
@@ -174,14 +232,16 @@ int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, in
174 image[7] = image[origin + 7]; 232 image[7] = image[origin + 7];
175 233
176 i = fwrite(image, 1, OF_FIRMWARE_LEN, f); 234 i = fwrite(image, 1, OF_FIRMWARE_LEN, f);
177 if(i < OF_FIRMWARE_LEN) { 235 if(i < OF_FIRMWARE_LEN)
178 perror(outfile); 236 {
237 fprintf(stderr,"[ERR] %s file write error\n", outfile);
179 fclose(f); 238 fclose(f);
180 return -9; 239 return -11;
181 } 240 }
182 241
183 printf("Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN, outfile); 242 fprintf(stderr,"[INFO] Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN, outfile);
184 243 fprintf(stderr,"[INFO] Patching succeeded!\n");
244
185 fclose(f); 245 fclose(f);
186 246
187 return 0; 247 return 0;
diff --git a/rbutil/mkmpioboot/mkmpioboot.h b/rbutil/mkmpioboot/mkmpioboot.h
index 794f9df765..4828ac953e 100644
--- a/rbutil/mkmpioboot/mkmpioboot.h
+++ b/rbutil/mkmpioboot/mkmpioboot.h
@@ -28,6 +28,15 @@
28extern "C" { 28extern "C" {
29#endif 29#endif
30 30
31/* Supported models */
32enum {
33 MODEL_UNKNOWN = -1,
34 MODEL_HD200 = 0,
35 MODEL_HD300,
36
37 NUM_MODELS
38};
39
31int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin); 40int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin);
32 41
33#ifdef __cplusplus 42#ifdef __cplusplus