1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2009 by Karl Kurbjun
10 * based on work by Shirour:
11 * http://www.mrobe.org/forum/viewtopic.php?f=6&t=2176
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
32 /* Notes about firmware:
33 * These notes are based on the work and observations of Shirour on the M:Robe
36 * The firmware for the M:Robe has basic encryption on it. The data is XORed
37 * and scrambled. The mr500_save_data function provides an implemenation of the
38 * encryption/decryption.
40 * When a firmware update is done the "{#4F494D4346575550#}" folder is stored
41 * in the system folder on the player. The "{#4F494D4346575550#}" should only
42 * contain the encrypted N5002-BD.BIN file. At the end of a firmware update
43 * the "{#4F494D4346575550#}" folder and it's contents are removed from the
46 * An interesting note is that the name "{#4F494D4346575550#}" is actually the
47 * Hex representation of the magic text found at the beginning of the firmware
51 /* These two arrays are used for descrambling or scrambling the data */
52 int decrypt_array
[16]={2, 0, 3, 1, 5, 7, 4, 6, 11, 10, 9, 8, 14, 12, 13, 15};
53 int encrypt_array
[16];
55 /* mr500_patch_file: This function modifies the specified file with the patches
59 * filename: text filename
60 * patches: pointer to structure array of patches
61 * num_patches: number of patches to apply (applied in reverse order)
64 * Returns 0 if there was no error, -1 if there was an error
66 int mr500_patch_file(char *filename
, struct patch_single
*patches
,
72 /* Open the file write only. */
73 fdo
= open(filename
, O_WRONLY
);
79 while(num_patches
--) {
80 /* seek to patch offset */
81 if(lseek(fdo
, patches
[num_patches
].offset
, SEEK_SET
)
82 != patches
[num_patches
].offset
) {
87 /* Make sure patch is written in little endian format */
88 endian_int
= htole32(patches
[num_patches
].value
);
90 /* Write the patch value to the file */
91 if(write(fdo
, (void *) &endian_int
, sizeof(endian_int
)) < 0) {
97 /* Close the file and check for errors */
105 /* mr500_save_header: This function saves the Olympus header to the firmware
106 * image. The values stored in the header are explained above. Note that this
107 * will truncate a file. The header is stored in little endian format.
110 * filename: text filename
111 * header: pointer to header structure to be saved
114 * Returns 0 if there was no error, -1 if there was an error
116 int mr500_save_header(char *filename
, struct olympus_header
*header
) {
120 /* Temporary header used for storing the header in little endian. */
121 struct olympus_header save
;
123 /* Open the file write only and truncate it. If it doesn't exist create. */
124 fdo
= open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, S_IRUSR
| S_IWUSR
);
130 /* Header is stored at offset 0 (Not really needed) */
131 if(lseek(fdo
, 0, SEEK_SET
) != 0) {
135 /* Convert header to Little Endian */
136 memcpy(&save
.magic_name
, &header
->magic_name
, 8*sizeof(int8_t));
137 save
.unknown
= htole32(header
->unknown
);
138 save
.header_length
= htole16(header
->header_length
);
139 save
.flags
= htole16(header
->flags
);
140 save
.unknown_zeros
= htole32(header
->unknown_zeros
);
141 save
.image_length
= htole32(header
->image_length
);
143 /* Write the header to the file */
144 if(write(fdo
, (void *) &save
, sizeof(save
)) < 0) {
148 /* Close the file and check for errors */
149 if(close (fdo
) < 0) {
156 /* mr500_read_header: This function reads the Olympus header and converts it to
157 * the host endian format. The values stored in the header are explained above.
158 * The header is stored in little endian format.
161 * filename: text filename
162 * header: pointer to header structure to store header read from file
165 * Returns 0 if there was no error, -1 if there was an error
167 int mr500_read_header(char *filename
, struct olympus_header
*header
) {
171 /* Open the file read only */
172 fdi
= open(filename
, O_RDONLY
);
178 /* Header is stored at offset 0 (Not really needed) */
179 if(lseek(fdi
, 0, SEEK_SET
) != 0) {
183 /* Read in the header */
184 if(read(fdi
, (void *) header
, sizeof(*header
)) < 0) {
188 /* Convert header to system endian */
189 header
->unknown
= le32toh(header
->unknown
);
190 header
->header_length
= le16toh(header
->header_length
);
191 header
->flags
= le16toh(header
->flags
);
192 header
->unknown_zeros
= le32toh(header
->unknown_zeros
);
193 header
->image_length
= le32toh(header
->image_length
);
195 /* Close the file and check for errors */
196 if(close (fdi
) < 0) {
203 /* mr500_save_crc: This function saves the 'CRC' of the Olympus firmware image.
204 * Note that the 'CRC' must be calculated on the decrytped image. It is stored
208 * filename: text filename
209 * offset: Offset to store the 'CRC' (header size + data size)
210 * crc_value: pointer to crc value to save
213 * Returns 0 if there was no error, -1 if there was an error
215 int mr500_save_crc(char *filename
, off_t offset
, uint32_t *crc_value
) {
220 /* Open the file write only */
221 fdo
= open(filename
, O_WRONLY
);
227 /* Seek to offset and check for errors */
228 if(lseek(fdo
, offset
, SEEK_SET
) != offset
) {
232 /* Convert 'CRC' to little endian from system native endian */
233 save_crc
= htole32(*crc_value
);
235 /* Write the 'CRC' and check for errors */
236 if(write(fdo
, (void *) &save_crc
, sizeof(unsigned int)) < 0) {
240 /* Close the file and check for errors */
241 if(close (fdo
) < 0) {
248 /* mr500_read_crc: This function reads the 'CRC' of the Olympus firmware image.
249 * Note that the 'CRC' is calculated on the decrytped values. It is stored
253 * filename: text filename
254 * offset: Offset to read the 'CRC' (header size + data size)
255 * crc_value: pointer to crc value to save
258 * Returns 0 if there was no error, -1 if there was an error
260 int mr500_read_crc(char *filename
, off_t offset
, uint32_t *crc_value
) {
264 /* Open the file read only */
265 fdi
= open(filename
, O_RDONLY
);
271 /* Seek to offset and check for errors */
272 if(lseek(fdi
, offset
, SEEK_SET
) != offset
) {
276 /* Read in the 'CRC' */
277 if(read(fdi
, (void *) crc_value
, sizeof(uint32_t)) < 0) {
281 /* Convert the 'CRC' from little endian to system native format */
282 *crc_value
= le32toh(*crc_value
);
284 /* Close the file and check for errors */
285 if(close (fdi
) < 0) {
292 /* mr500_calculate_crc: This function calculates the 'CRC' of the Olympus
293 * firmware image. Note that the 'CRC' must be calculated on decrytped values.
294 * It is stored in little endian.
297 * filename: text filename
298 * offset: Offset to the start of the data (header size)
299 * length: Length of data to calculate
300 * crc_value: pointer to crc value to save
303 * Returns 0 if there was no error, -1 if there was an error
305 int mr500_calculate_crc( char *filename
, off_t offset
, unsigned int length
,
306 uint32_t *crc_value
){
311 /* Open the file read only */
312 fdi
= open(filename
, O_RDONLY
);
318 /* Seek to offset and check for errors */
319 if(lseek(fdi
, offset
, SEEK_SET
) != offset
) {
323 /* Initialize the crc_value to make sure this starts at 0 */
325 /* Run this loop till the entire sum is created */
327 /* Read an integer at a time */
328 if(read(fdi
, &temp
, sizeof(uint32_t)) < 0) {
333 /* Keep summing the values */
337 /* Close the file and check for errors */
338 if(close (fdi
) < 0) {
345 /* mr500_save_data: This function encypts or decrypts the Olympus firmware
346 * image based on the dictionary passed to it.
349 * source_filename: text filename where data is read from
350 * dest_filename: text filename where data is written to
351 * offset: Offset to the start of the data (header size)
352 * length: Length of data to modify
353 * dictionary: pointer to dictionary used for scrambling
356 * Returns 0 if there was no error, -1 if there was an error
359 char *source_filename
, char *dest_filename
, off_t offset
,
360 unsigned int length
, int* dictionary
) {
365 /* read_count stores the number of bytes actually read */
368 /* read_request stores the number of bytes to be requested */
371 /* These two buffers are used for reading data and scrambling or
374 int8_t buffer_original
[16];
375 int8_t buffer_modified
[16];
377 /* Open input read only, output write only */
378 fdi
= open(source_filename
, O_RDONLY
);
379 fdo
= open(dest_filename
, O_WRONLY
);
381 /* If there was an error loading the files set ret appropriately */
382 if(fdi
<0 || fdo
< 0) {
386 /* Input file: Seek to offset and check for errors */
387 if(lseek(fdi
, offset
, SEEK_SET
) != offset
) {
391 /* Output file: Seek to offset and check for errors */
392 if(lseek(fdo
, offset
, SEEK_SET
) != offset
) {
396 /* Run this loop till size is 0 */
398 /* Choose the amount of data to read - normally in 16 byte chunks, but
399 * when the end of the file is near may be less.
401 if( length
> sizeof(buffer_original
)){
402 read_request
= sizeof(buffer_original
);
404 read_request
= length
;
407 /* Read in the data */
408 read_count
= read(fdi
, (void *) &buffer_original
, read_request
);
410 /* If there was an error set the flag and break */
416 for(i
=0; i
<read_count
; i
++) {
417 /* XOR all of the bits to de/encrypt them */
418 buffer_original
[i
] ^= 0xFF;
419 /* Handle byte scrambling */
420 buffer_modified
[dictionary
[i
]] = buffer_original
[i
];
423 /* write the data: If there was an error set the flag and break */
424 if(write(fdo
, (void *) &buffer_modified
, read_count
) < 0) {
428 } while (length
-= read_count
);
430 /* Close the files and check for errors */
431 if(close (fdi
) < 0) {
434 if(close (fdo
) < 0) {
441 /* mr500_init: This function initializes the encryption array
449 int mr500_init(void) {
451 /* Initialize the encryption array */
452 for(i
=0; i
<16; i
++) {
453 encrypt_array
[decrypt_array
[i
]]=i
;