···11+/***************************************************************************
22+ * __________ __ ___.
33+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
44+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
55+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
66+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
77+ * \/ \/ \/ \/ \/
88+ *
99+ * Copyright (C) 2009 by Karl Kurbjun
1010+ * $Id$
1111+ *
1212+ * All files in this archive are subject to the GNU General Public License.
1313+ * See the file COPYING in the source tree root for full license agreement.
1414+ *
1515+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1616+ * KIND, either express or implied.
1717+ *
1818+ ****************************************************************************/
1919+2020+#include <stdio.h>
2121+#include <errno.h>
2222+#include <inttypes.h>
2323+#include <string.h>
2424+#include "mr500.h"
2525+2626+/* This is the patch necessary for the SVG exploit (decrypted) */
2727+struct patch_single hack[] = { {0x29B28, 0xE12FFF30},
2828+ {0x2F960, 0xE12FFF30} };
2929+3030+static void usage(void)
3131+{
3232+ printf( "Usage: mk500boot <options> <input file> [output file]\n"
3333+ "options:\n"
3434+ "\t-decrypt Decrypt the input file and save the output file\n"
3535+ "\t-encrypt Encrypt the input file and save the output file\n"
3636+ "\t-patch Patch the input file with the SVF hack\n\n");
3737+3838+ exit(1);
3939+}
4040+4141+/* This is a fake flag that is used to let the tool know what's up */
4242+#define HEADER_DECRYPTED 0x8000
4343+4444+void display_header(struct olympus_header *header) {
4545+ printf("Magic Name: \t%s\n", header->magic_name);
4646+ printf("Unknown: \t0x%08hX\n", header->unknown);
4747+ printf("Header Length: \t0x%04X\n", header->header_length);
4848+ printf("Flags: \t\t0x%04X\n", header->flags);
4949+ printf("Unknonwn Zeros: 0x%08X\n", header->unknown_zeros);
5050+ printf("Image Length: \t0x%08X\n", header->image_length);
5151+}
5252+5353+/* This is a demonstration of the encryption and decryption process.
5454+ * It patches a FW image to include the SVG exploit.
5555+ */
5656+int main (int argc, char *argv[]) {
5757+ uint32_t checksum;
5858+ uint32_t stored_crc;
5959+6060+ enum operations {
6161+ decrypt,
6262+ encrypt,
6363+ patch
6464+ } operation;
6565+6666+ char *encrypt_file;
6767+ char *decrypt_file;
6868+6969+ struct olympus_header header;
7070+7171+ if (argc < 2) {
7272+ usage();
7373+ return -1;
7474+ }
7575+7676+ if(!strcmp(argv[1], "-decrypt")) {
7777+ if(argc < 3) {
7878+ usage();
7979+ return -1;
8080+ }
8181+ encrypt_file=argv[2];
8282+ decrypt_file=argv[3];
8383+ operation = decrypt;
8484+ } else if(!strcmp(argv[1], "-encrypt")) {
8585+ if(argc < 3) {
8686+ usage();
8787+ return -1;
8888+ }
8989+ decrypt_file = argv[2];
9090+ encrypt_file = argv[3];
9191+ operation = encrypt;
9292+ } else if(!strcmp(argv[1], "-patch")) {
9393+ decrypt_file = argv[2];
9494+ encrypt_file = argv[3];
9595+ operation = patch;
9696+ } else {
9797+ return -1;
9898+ }
9999+100100+ /* Initialize encryption/decryption routine */
101101+ mr500_init();
102102+103103+ if(operation == decrypt) {
104104+ /* Read in the header of the encrypted file */
105105+ if(mr500_read_header(encrypt_file, &header) < 0 ) {
106106+ printf("ERROR: Unable to read header: %s\n", strerror(errno));
107107+ return -1;
108108+ }
109109+110110+ /* Read CRC of encrypted file */
111111+ if(mr500_read_crc(encrypt_file,
112112+ header.header_length+header.image_length, &stored_crc) < 0 ) {
113113+ printf("ERROR: Unable to read CRC: %s\n", strerror(errno));
114114+ return -1;
115115+ }
116116+117117+ /* Display the header information */
118118+ printf("File format:\n");
119119+120120+ printf("*****Header*****\n");
121121+ display_header(&header);
122122+ printf("****************\n\n");
123123+124124+ printf("*****Image******\n\n");
125125+126126+ printf("*****Footer*****\n");
127127+ printf("Checksum: \t0x%08X\n", stored_crc);
128128+ printf("****************\n\n");
129129+130130+ printf("Writing Decrypted file...\n");
131131+132132+ /*********************************************************************
133133+ * Save a decrypted file
134134+ **********************************************************************/
135135+136136+ /* Check to make sure this is a encrypted file (bogus flag not set) */
137137+ if(header.flags & HEADER_DECRYPTED) {
138138+ printf("ERROR: This appears to be a decrypted file! Quitting\n");
139139+ return -1;
140140+ }
141141+142142+ /* Check to make sure MAGIC string matches expected*/
143143+ if(strncmp((char *)header.magic_name, "OIMCFWUP", 8)) {
144144+ printf("ERROR: Magic string does not match expected! Quitting\n");
145145+ return -1;
146146+ }
147147+148148+ /* Set a bogus flag to let the tool know that this is a decrypted file*/
149149+ header.flags |= HEADER_DECRYPTED;
150150+151151+ /* Start by writing out the header */
152152+ if(mr500_save_header(decrypt_file, &header) < 0 ) {
153153+ printf("ERROR: Unable to save header: %s\n", strerror(errno));
154154+ return -1;
155155+ }
156156+157157+ /* Read encrypted data and save decrypted data */
158158+ if(mr500_save_data( encrypt_file, decrypt_file, header.header_length,
159159+ header.image_length, decrypt_array) < 0 ) {
160160+ printf("ERROR: Unable to save decrypted data: %s\n", strerror(errno));
161161+ return -1;
162162+ }
163163+164164+ printf("Calculating Checksum...\n");
165165+ /* Calculate CRC of decrypted data */
166166+ if(mr500_calculate_crc( decrypt_file, header.header_length,
167167+ header.image_length, &checksum) < 0 ) {
168168+ printf("ERROR: Unable to calculate CRC: %s\n", strerror(errno));
169169+ return -1;
170170+ }
171171+172172+ printf("Calculated Checksum: \n\t\t0x%08X\n", checksum);
173173+174174+ /* Double check to make sure that the two CRCs match */
175175+ if(checksum!=stored_crc) {
176176+ printf("\tERROR: \tCalculated checksum: \t0x%08X and\n", checksum);
177177+ printf("\t\tStored checksum: \t0x%08X do not match\n", stored_crc);
178178+ return -1;
179179+ } else {
180180+ printf("\tOK: Calculated checksum and stored checksum match.\n");
181181+ }
182182+183183+ printf("Saving Checksum...\n");
184184+ /* Save the calculated CRC to the file */
185185+ if(mr500_save_crc(decrypt_file, header.header_length+header.image_length,
186186+ &checksum) < 0 ) {
187187+ printf("ERROR: Unable to save CRC: %s\n", strerror(errno));
188188+ return -1;
189189+ }
190190+191191+ } else if(operation == patch) {
192192+193193+ /**********************************************************************
194194+ * Patch decryped file with SVG exploit
195195+ **********************************************************************/
196196+ printf("Patching decrypted file.\n");
197197+198198+ /* Read in the header of the encrypted file */
199199+ if(mr500_read_header(decrypt_file, &header) < 0 ) {
200200+ printf("ERROR: Unable to read header: %s\n", strerror(errno));
201201+ return -1;
202202+ }
203203+204204+ /* Check to make sure this is a decrypted file (bogus flag not set) */
205205+ if(!(header.flags & HEADER_DECRYPTED)) {
206206+ printf("ERROR: This appears to be a encrypted file! Quitting\n");
207207+ return -1;
208208+ }
209209+210210+ /* Check to make sure MAGIC string matches expected*/
211211+ if(strncmp((char *)header.magic_name, "OIMCFWUP", 8)) {
212212+ printf("ERROR: Magic string does not match expected! Quitting\n");
213213+ return -1;
214214+ }
215215+216216+ printf("File Header:\n");
217217+ display_header(&header);
218218+219219+ if(mr500_patch_file (decrypt_file, hack, 2) < 0 ) {
220220+ printf("ERROR: Unable to patch file: %s\n", strerror(errno));
221221+ return -1;
222222+ }
223223+224224+ printf("\nCalculating new CRC\n");
225225+226226+ /* Calculate the 'CRC' of the patched file */
227227+ if(mr500_calculate_crc( decrypt_file, header.header_length,
228228+ header.image_length, &checksum) < 0 ) {
229229+ printf("ERROR: Unable to calculate CRC: %s\n", strerror(errno));
230230+ return -1;
231231+ }
232232+233233+ printf("Calculated CRC: \n\t\t0x%08X\n", checksum);
234234+ /* Store the calculated 'CRC' (not encrypted) */
235235+ if(mr500_save_crc(decrypt_file, header.header_length+header.image_length,
236236+ &checksum) < 0 ) {
237237+ printf("ERROR: Unable to save CRC: %s\n", strerror(errno));
238238+ return -1;
239239+ }
240240+241241+ } else if(operation == encrypt) {
242242+243243+ /**********************************************************************
244244+ * Save an encrypted file
245245+ **********************************************************************/
246246+ printf("Saving Encrypted file\n");
247247+248248+ /* Read in the header of the encrypted file */
249249+ if(mr500_read_header(decrypt_file, &header) < 0 ) {
250250+ printf("ERROR: Unable to read header: %s\n", strerror(errno));
251251+ return -1;
252252+ }
253253+254254+ /* Check to make sure this is a decrypted file (bogus flag not set) */
255255+ if(!(header.flags & HEADER_DECRYPTED)) {
256256+ printf("ERROR: This appears to be a encrypted file! Quitting\n");
257257+ return -1;
258258+ }
259259+260260+ /* Check to make sure MAGIC string matches expected*/
261261+ if(strncmp((char *)header.magic_name, "OIMCFWUP", 7)) {
262262+ printf("ERROR: Magic string does not match expected! Quitting\n");
263263+ return -1;
264264+ }
265265+266266+ /* Remove the bogus flag */
267267+ header.flags &= ~HEADER_DECRYPTED;
268268+269269+ printf("File Header:\n");
270270+ display_header(&header);
271271+272272+ /* Header is not encrypted, save it */
273273+ if(mr500_save_header(encrypt_file, &header) < 0 ) {
274274+ printf("ERROR: Unable to save header: %s\n", strerror(errno));
275275+ return -1;
276276+ }
277277+278278+ /* Read CRC of decrypted file */
279279+ if(mr500_read_crc(decrypt_file,
280280+ header.header_length+header.image_length, &stored_crc) < 0 ) {
281281+ printf("ERROR: Unable to read CRC: %s\n", strerror(errno));
282282+ return -1;
283283+ }
284284+285285+ /* Calculate the 'CRC' of the decrypted data */
286286+ if(mr500_calculate_crc( decrypt_file, header.header_length,
287287+ header.image_length, &checksum) < 0 ) {
288288+ printf("ERROR: Unable to calculate CRC: %s\n", strerror(errno));
289289+ return -1;
290290+ }
291291+292292+ if(stored_crc != checksum) {
293293+ printf("\nERROR: Stored and calculated checksums do not match!\n"
294294+ "\tFile has been improperly modified. Quitting\n");
295295+ return -1;
296296+ }
297297+298298+ printf("Encrypting data...\n");
299299+300300+ /* Write the encrypted data to a file */
301301+ if(mr500_save_data( decrypt_file, encrypt_file, header.header_length,
302302+ header.image_length, encrypt_array) < 0 ) {
303303+ printf("ERROR: Unable to save encrypted data: %s\n", strerror(errno));
304304+ return -1;
305305+ }
306306+307307+ printf("Saving CRC\n");
308308+309309+ /* Store the calculated 'CRC' (not encrypted) */
310310+ if(mr500_save_crc(encrypt_file, header.header_length+header.image_length,
311311+ &checksum) < 0 ) {
312312+ printf("ERROR: Unable to save CRC: %s\n", strerror(errno));
313313+ return -1;
314314+ }
315315+316316+ printf("File sucesfully encrypted!\n");
317317+ }
318318+319319+ printf("Done\n");
320320+ return 0;
321321+}
322322+
+457
tools/mr500.c
···11+/***************************************************************************
22+ * __________ __ ___.
33+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
44+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
55+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
66+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
77+ * \/ \/ \/ \/ \/
88+ *
99+ * Copyright (C) 2009 by Karl Kurbjun
1010+ * based on work by Shirour:
1111+ * http://www.mrobe.org/forum/viewtopic.php?f=6&t=2176
1212+ * $Id$
1313+ *
1414+ * All files in this archive are subject to the GNU General Public License.
1515+ * See the file COPYING in the source tree root for full license agreement.
1616+ *
1717+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1818+ * KIND, either express or implied.
1919+ *
2020+ ****************************************************************************/
2121+2222+#include <stdio.h>
2323+#include <string.h>
2424+#include <stdlib.h>
2525+#include <fcntl.h>
2626+#include <errno.h>
2727+#include <unistd.h>
2828+#include <inttypes.h>
2929+#include <sys/stat.h>
3030+#include "mr500.h"
3131+3232+/* Notes about firmware:
3333+ * These notes are based on the work and observations of Shirour on the M:Robe
3434+ * forums.
3535+ *
3636+ * The firmware for the M:Robe has basic encryption on it. The data is XORed
3737+ * and scrambled. The mr500_save_data function provides an implemenation of the
3838+ * encryption/decryption.
3939+ *
4040+ * When a firmware update is done the "{#4F494D4346575550#}" folder is stored
4141+ * in the system folder on the player. The "{#4F494D4346575550#}" should only
4242+ * contain the encrypted N5002-BD.BIN file. At the end of a firmware update
4343+ * the "{#4F494D4346575550#}" folder and it's contents are removed from the
4444+ * player.
4545+ *
4646+ * An interesting note is that the name "{#4F494D4346575550#}" is actually the
4747+ * Hex representation of the magic text found at the beginning of the firmware
4848+ * image "OIMCFWUP".
4949+ */
5050+5151+/* These two arrays are used for descrambling or scrambling the data */
5252+int decrypt_array[16]={2, 0, 3, 1, 5, 7, 4, 6, 11, 10, 9, 8, 14, 12, 13, 15};
5353+int encrypt_array[16];
5454+5555+/* mr500_patch_file: This function modifies the specified file with the patches
5656+ * struct.
5757+ *
5858+ * Parameters:
5959+ * filename: text filename
6060+ * patches: pointer to structure array of patches
6161+ * num_patches: number of patches to apply (applied in reverse order)
6262+ *
6363+ * Returns:
6464+ * Returns 0 if there was no error, -1 if there was an error
6565+ */
6666+int mr500_patch_file(char *filename, struct patch_single *patches,
6767+ int num_patches) {
6868+ int fdo;
6969+ int ret=0;
7070+ uint32_t endian_int;
7171+7272+ /* Open the file write only. */
7373+ fdo = open(filename, O_WRONLY);
7474+7575+ if(fdo<0) {
7676+ ret=-1;
7777+ }
7878+7979+ while(num_patches--) {
8080+ /* seek to patch offset */
8181+ if(lseek(fdo, patches[num_patches].offset, SEEK_SET)
8282+ != patches[num_patches].offset) {
8383+ ret=-1;
8484+ break;
8585+ }
8686+8787+ /* Make sure patch is written in little endian format */
8888+ endian_int = htole32(patches[num_patches].value);
8989+9090+ /* Write the patch value to the file */
9191+ if(write(fdo, (void *) &endian_int, sizeof(endian_int)) < 0) {
9292+ ret = -1;
9393+ break;
9494+ }
9595+ }
9696+9797+ /* Close the file and check for errors */
9898+ if(close (fdo) < 0) {
9999+ ret = -1;
100100+ }
101101+102102+ return ret;
103103+}
104104+105105+/* mr500_save_header: This function saves the Olympus header to the firmware
106106+ * image. The values stored in the header are explained above. Note that this
107107+ * will truncate a file. The header is stored in little endian format.
108108+ *
109109+ * Parameters:
110110+ * filename: text filename
111111+ * header: pointer to header structure to be saved
112112+ *
113113+ * Returns:
114114+ * Returns 0 if there was no error, -1 if there was an error
115115+ */
116116+int mr500_save_header(char *filename, struct olympus_header *header) {
117117+ int fdo;
118118+ int ret=0;
119119+120120+ /* Temporary header used for storing the header in little endian. */
121121+ struct olympus_header save;
122122+123123+ /* Open the file write only and truncate it. If it doesn't exist create. */
124124+ fdo = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
125125+126126+ if(fdo<0) {
127127+ ret=-1;
128128+ }
129129+130130+ /* Header is stored at offset 0 (Not really needed) */
131131+ if(lseek(fdo, 0, SEEK_SET) != 0) {
132132+ ret=-1;
133133+ }
134134+135135+ /* Convert header to Little Endian */
136136+ memcpy(&save.magic_name, &header->magic_name, 8*sizeof(int8_t));
137137+ save.unknown = htole32(header->unknown);
138138+ save.header_length = htole16(header->header_length);
139139+ save.flags = htole16(header->flags);
140140+ save.unknown_zeros = htole32(header->unknown_zeros);
141141+ save.image_length = htole32(header->image_length);
142142+143143+ /* Write the header to the file */
144144+ if(write(fdo, (void *) &save, sizeof(save)) < 0) {
145145+ ret = -1;
146146+ }
147147+148148+ /* Close the file and check for errors */
149149+ if(close (fdo) < 0) {
150150+ ret = -1;
151151+ }
152152+153153+ return ret;
154154+}
155155+156156+/* mr500_read_header: This function reads the Olympus header and converts it to
157157+ * the host endian format. The values stored in the header are explained above.
158158+ * The header is stored in little endian format.
159159+ *
160160+ * Parameters:
161161+ * filename: text filename
162162+ * header: pointer to header structure to store header read from file
163163+ *
164164+ * Returns:
165165+ * Returns 0 if there was no error, -1 if there was an error
166166+ */
167167+int mr500_read_header(char *filename, struct olympus_header *header) {
168168+ int fdi;
169169+ int ret = 0;
170170+171171+ /* Open the file read only */
172172+ fdi = open(filename, O_RDONLY);
173173+174174+ if(fdi<0) {
175175+ ret=-1;
176176+ }
177177+178178+ /* Header is stored at offset 0 (Not really needed) */
179179+ if(lseek(fdi, 0, SEEK_SET) != 0) {
180180+ ret=-1;
181181+ }
182182+183183+ /* Read in the header */
184184+ if(read(fdi, (void *) header, sizeof(*header)) < 0) {
185185+ ret = -1;
186186+ }
187187+188188+ /* Convert header to system endian */
189189+ header->unknown = le32toh(header->unknown);
190190+ header->header_length = le16toh(header->header_length);
191191+ header->flags = le16toh(header->flags);
192192+ header->unknown_zeros = le32toh(header->unknown_zeros);
193193+ header->image_length = le32toh(header->image_length);
194194+195195+ /* Close the file and check for errors */
196196+ if(close (fdi) < 0) {
197197+ ret = -1;
198198+ }
199199+200200+ return ret;
201201+}
202202+203203+/* mr500_save_crc: This function saves the 'CRC' of the Olympus firmware image.
204204+ * Note that the 'CRC' must be calculated on the decrytped image. It is stored
205205+ * in little endian.
206206+ *
207207+ * Parameters:
208208+ * filename: text filename
209209+ * offset: Offset to store the 'CRC' (header size + data size)
210210+ * crc_value: pointer to crc value to save
211211+ *
212212+ * Returns:
213213+ * Returns 0 if there was no error, -1 if there was an error
214214+ */
215215+int mr500_save_crc(char *filename, off_t offset, uint32_t *crc_value) {
216216+ int fdo;
217217+ int ret = 0;
218218+ uint32_t save_crc;
219219+220220+ /* Open the file write only */
221221+ fdo = open(filename, O_WRONLY);
222222+223223+ if(fdo<0) {
224224+ ret=-1;
225225+ }
226226+227227+ /* Seek to offset and check for errors */
228228+ if(lseek(fdo, offset, SEEK_SET) != offset) {
229229+ ret=-1;
230230+ }
231231+232232+ /* Convert 'CRC' to little endian from system native endian */
233233+ save_crc = htole32(*crc_value);
234234+235235+ /* Write the 'CRC' and check for errors */
236236+ if(write(fdo, (void *) &save_crc, sizeof(unsigned int)) < 0) {
237237+ ret = -1;
238238+ }
239239+240240+ /* Close the file and check for errors */
241241+ if(close (fdo) < 0) {
242242+ ret = -1;
243243+ }
244244+245245+ return ret;
246246+}
247247+248248+/* mr500_read_crc: This function reads the 'CRC' of the Olympus firmware image.
249249+ * Note that the 'CRC' is calculated on the decrytped values. It is stored
250250+ * in little endian.
251251+ *
252252+ * Parameters:
253253+ * filename: text filename
254254+ * offset: Offset to read the 'CRC' (header size + data size)
255255+ * crc_value: pointer to crc value to save
256256+ *
257257+ * Returns:
258258+ * Returns 0 if there was no error, -1 if there was an error
259259+ */
260260+int mr500_read_crc(char *filename, off_t offset, uint32_t *crc_value) {
261261+ int fdi;
262262+ int ret = 0;
263263+264264+ /* Open the file read only */
265265+ fdi = open(filename, O_RDONLY);
266266+267267+ if(fdi<0) {
268268+ ret = -1;
269269+ }
270270+271271+ /* Seek to offset and check for errors */
272272+ if(lseek(fdi, offset, SEEK_SET) != offset) {
273273+ ret=-1;
274274+ }
275275+276276+ /* Read in the 'CRC' */
277277+ if(read(fdi, (void *) crc_value, sizeof(uint32_t)) < 0) {
278278+ ret = -1;
279279+ }
280280+281281+ /* Convert the 'CRC' from little endian to system native format */
282282+ *crc_value = le32toh(*crc_value);
283283+284284+ /* Close the file and check for errors */
285285+ if(close (fdi) < 0) {
286286+ ret = -1;
287287+ }
288288+289289+ return ret;
290290+}
291291+292292+/* mr500_calculate_crc: This function calculates the 'CRC' of the Olympus
293293+ * firmware image. Note that the 'CRC' must be calculated on decrytped values.
294294+ * It is stored in little endian.
295295+ *
296296+ * Parameters:
297297+ * filename: text filename
298298+ * offset: Offset to the start of the data (header size)
299299+ * length: Length of data to calculate
300300+ * crc_value: pointer to crc value to save
301301+ *
302302+ * Returns:
303303+ * Returns 0 if there was no error, -1 if there was an error
304304+ */
305305+int mr500_calculate_crc( char *filename, off_t offset, unsigned int length,
306306+ uint32_t *crc_value){
307307+ uint32_t temp;
308308+ int fdi;
309309+ int ret = 0;
310310+311311+ /* Open the file read only */
312312+ fdi = open(filename, O_RDONLY);
313313+314314+ if(fdi<0) {
315315+ ret = -1;
316316+ }
317317+318318+ /* Seek to offset and check for errors */
319319+ if(lseek(fdi, offset, SEEK_SET) != offset) {
320320+ ret=-1;
321321+ }
322322+323323+ /* Initialize the crc_value to make sure this starts at 0 */
324324+ *crc_value = 0;
325325+ /* Run this loop till the entire sum is created */
326326+ do {
327327+ /* Read an integer at a time */
328328+ if(read(fdi, &temp, sizeof(uint32_t)) < 0) {
329329+ ret = -1;
330330+ break;
331331+ }
332332+333333+ /* Keep summing the values */
334334+ *crc_value+=temp;
335335+ } while (length-=4);
336336+337337+ /* Close the file and check for errors */
338338+ if(close (fdi) < 0) {
339339+ ret = -1;
340340+ }
341341+342342+ return ret;
343343+}
344344+345345+/* mr500_save_data: This function encypts or decrypts the Olympus firmware
346346+ * image based on the dictionary passed to it.
347347+ *
348348+ * Parameters:
349349+ * source_filename: text filename where data is read from
350350+ * dest_filename: text filename where data is written to
351351+ * offset: Offset to the start of the data (header size)
352352+ * length: Length of data to modify
353353+ * dictionary: pointer to dictionary used for scrambling
354354+ *
355355+ * Returns:
356356+ * Returns 0 if there was no error, -1 if there was an error
357357+ */
358358+int mr500_save_data(
359359+ char *source_filename, char *dest_filename, off_t offset,
360360+ unsigned int length, int* dictionary) {
361361+ int fdi, fdo;
362362+ int ret = 0;
363363+ int i;
364364+365365+ /* read_count stores the number of bytes actually read */
366366+ int read_count;
367367+368368+ /* read_request stores the number of bytes to be requested */
369369+ int read_request;
370370+371371+ /* These two buffers are used for reading data and scrambling or
372372+ * descrambling
373373+ */
374374+ int8_t buffer_original[16];
375375+ int8_t buffer_modified[16];
376376+377377+ /* Open input read only, output write only */
378378+ fdi = open(source_filename, O_RDONLY);
379379+ fdo = open(dest_filename, O_WRONLY);
380380+381381+ /* If there was an error loading the files set ret appropriately */
382382+ if(fdi<0 || fdo < 0) {
383383+ ret = -1;
384384+ }
385385+386386+ /* Input file: Seek to offset and check for errors */
387387+ if(lseek(fdi, offset, SEEK_SET) != offset) {
388388+ ret=-1;
389389+ }
390390+391391+ /* Output file: Seek to offset and check for errors */
392392+ if(lseek(fdo, offset, SEEK_SET) != offset) {
393393+ ret=-1;
394394+ }
395395+396396+ /* Run this loop till size is 0 */
397397+ do {
398398+ /* Choose the amount of data to read - normally in 16 byte chunks, but
399399+ * when the end of the file is near may be less.
400400+ */
401401+ if( length > sizeof(buffer_original)){
402402+ read_request = sizeof(buffer_original);
403403+ } else {
404404+ read_request = length;
405405+ }
406406+407407+ /* Read in the data */
408408+ read_count = read(fdi, (void *) &buffer_original, read_request);
409409+410410+ /* If there was an error set the flag and break */
411411+ if(read_count < 0) {
412412+ ret = -1;
413413+ break;
414414+ }
415415+416416+ for(i=0; i<read_count; i++) {
417417+ /* XOR all of the bits to de/encrypt them */
418418+ buffer_original[i] ^= 0xFF;
419419+ /* Handle byte scrambling */
420420+ buffer_modified[dictionary[i]] = buffer_original[i];
421421+ }
422422+423423+ /* write the data: If there was an error set the flag and break */
424424+ if(write(fdo, (void *) &buffer_modified, read_count) < 0) {
425425+ ret = -1;
426426+ break;
427427+ }
428428+ } while (length -= read_count);
429429+430430+ /* Close the files and check for errors */
431431+ if(close (fdi) < 0) {
432432+ ret = -1;
433433+ }
434434+ if(close (fdo) < 0) {
435435+ ret = -1;
436436+ }
437437+438438+ return ret;
439439+}
440440+441441+/* mr500_init: This function initializes the encryption array
442442+ *
443443+ * Parameters:
444444+ * None
445445+ *
446446+ * Returns:
447447+ * Returns 0
448448+ */
449449+int mr500_init(void) {
450450+ int i;
451451+ /* Initialize the encryption array */
452452+ for(i=0; i<16; i++) {
453453+ encrypt_array[decrypt_array[i]]=i;
454454+ }
455455+ return 0;
456456+}
457457+
+56
tools/mr500.h
···11+/***************************************************************************
22+ * __________ __ ___.
33+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
44+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
55+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
66+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
77+ * \/ \/ \/ \/ \/
88+ *
99+ * Copyright (C) 2009 by Karl Kurbjun
1010+ * $Id$
1111+ *
1212+ * All files in this archive are subject to the GNU General Public License.
1313+ * See the file COPYING in the source tree root for full license agreement.
1414+ *
1515+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1616+ * KIND, either express or implied.
1717+ *
1818+ ****************************************************************************/
1919+2020+#include <stdlib.h>
2121+extern int decrypt_array[];
2222+extern int encrypt_array[];
2323+2424+/* Notes about the header:
2525+ * The magic_name should always be "OIMCFWUP"
2626+ * Header length is always 18 bytes
2727+ * The flags have the following mask:
2828+ * CHECK_CRC 0x01 : Tells the firmware whether or not to check CRC
2929+ * ENDIAN_MODE 0x02 : Tells the OF whether to re-order the bytes
3030+ * The rest are unknown
3131+ * The image length is in bytes and is always 0x007F0000
3232+ */
3333+struct olympus_header {
3434+ int8_t magic_name[8];
3535+ uint32_t unknown;
3636+ uint16_t header_length;
3737+ uint16_t flags;
3838+ uint32_t unknown_zeros;
3939+ uint32_t image_length;
4040+} __attribute__((__packed__));
4141+4242+/* Patch entries should be saved in little endian format */
4343+struct patch_single {
4444+ off_t offset;
4545+ uint32_t value;
4646+};
4747+4848+int mr500_patch_file(char *, struct patch_single *, int);
4949+int mr500_save_header(char *, struct olympus_header *);
5050+int mr500_read_header(char *, struct olympus_header *);
5151+int mr500_save_crc(char *, off_t, uint32_t *);
5252+int mr500_read_crc(char *, off_t, uint32_t *);
5353+int mr500_calculate_crc(char *, off_t, unsigned int, uint32_t *);
5454+int mr500_save_data(char *, char *, off_t, unsigned int, int*);
5555+int mr500_init(void);
5656+