diff options
-rw-r--r-- | rbutil/mkmpioboot/main.c | 8 | ||||
-rw-r--r-- | rbutil/mkmpioboot/mkmpioboot.c | 136 | ||||
-rw-r--r-- | rbutil/mkmpioboot/mkmpioboot.h | 9 |
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 | |
33 | static char *mpio_string = "HD200 HDD Audio Ver113005"; | 33 | /* Descriptive name of these models */ |
34 | 34 | const 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 */ | ||
41 | static 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 */ | ||
48 | static const int rb_model_num[] = { | ||
49 | [MODEL_HD200] = 69, | ||
50 | [MODEL_HD300] = 70, | ||
51 | }; | ||
52 | |||
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", | ||
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 | ||
52 | static long checksum(unsigned char* buf, unsigned long length) | 76 | static 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 @@ | |||
28 | extern "C" { | 28 | extern "C" { |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | /* Supported models */ | ||
32 | enum { | ||
33 | MODEL_UNKNOWN = -1, | ||
34 | MODEL_HD200 = 0, | ||
35 | MODEL_HD300, | ||
36 | |||
37 | NUM_MODELS | ||
38 | }; | ||
39 | |||
31 | int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin); | 40 | int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin); |
32 | 41 | ||
33 | #ifdef __cplusplus | 42 | #ifdef __cplusplus |