summaryrefslogtreecommitdiff
path: root/utils/ypr0tools/fwdecrypt.c
diff options
context:
space:
mode:
authorLorenzo Miori <memorys60@gmail.com>2013-07-09 18:20:08 +0200
committerThomas Martitz <kugel@rockbox.org>2013-09-07 15:56:07 +0200
commitda8a6a90c33f8bf8f2cad9ff009d813b8b7fbaab (patch)
tree6cf1d0f79ca72df989c35486c81c1999cc85a116 /utils/ypr0tools/fwdecrypt.c
parentcb27d4066a3a96cfc3758dff47c59cbadc3402ee (diff)
downloadrockbox-da8a6a90c33f8bf8f2cad9ff009d813b8b7fbaab.zip
rockbox-da8a6a90c33f8bf8f2cad9ff009d813b8b7fbaab.tar.gz
rockbox-da8a6a90c33f8bf8f2cad9ff009d813b8b7fbaab.tar.bz2
rockbox-da8a6a90c33f8bf8f2cad9ff009d813b8b7fbaab.tar.xz
Firmware tools for Samsung YP-R0/YP-R1 (and possibly others)
They have been rewritten for being completely free and as fast as possible. Successfully extracted, patched, repacked and flashed original firmware (tested on device and it worked) Change-Id: I74d47d13f2dc3a2832a0d6821d3c2182dfd4b33b Reviewed-on: http://gerrit.rockbox.org/506 Reviewed-by: Thomas Martitz <kugel@rockbox.org> Tested-by: Thomas Martitz <kugel@rockbox.org>
Diffstat (limited to 'utils/ypr0tools/fwdecrypt.c')
-rw-r--r--utils/ypr0tools/fwdecrypt.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/utils/ypr0tools/fwdecrypt.c b/utils/ypr0tools/fwdecrypt.c
new file mode 100644
index 0000000..eb611fe
--- /dev/null
+++ b/utils/ypr0tools/fwdecrypt.c
@@ -0,0 +1,168 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2013 Lorenzo Miori
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "common.h"
+
+static char* output_dir = NULL;
+static FILE* input_file = NULL;
+static struct firmware_data fw;
+
+static void cleanup(void)
+{
+ for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
+ {
+ free(fw.component_data[i]);
+ }
+}
+
+static void die(int error)
+{
+ if (input_file != NULL)
+ fclose(input_file);
+ free(output_dir);
+ cleanup();
+ exit(error);
+}
+
+int main(int argc, char **argv)
+{
+ FILE* component_handle = NULL;
+ FILE* rev_info_file = NULL;
+ char* tmp_path = malloc(MAX_PATH);
+ int error = 0;
+ bool md5sum_error = false;
+
+ memset(&fw, 0, sizeof(fw));
+
+ if (argc < 2)
+ {
+ printf("Decrypts Samsung YP-R0/YP-R1 ROM file format\n"
+ "Usage: fwdecrypt <ROM file path\n"
+ );
+ return 1;
+ }
+
+ output_dir = malloc(MAX_PATH);
+ output_dir[0] = '\0';
+ if (argc > 2)
+ {
+ strcpy(output_dir, argv[2]);
+ }
+
+ /* open the output file for write */
+ input_file = fopen(argv[1], "rb");
+ if (input_file == NULL)
+ {
+ fprintf(stderr, "Cannot open file for reading: %m\n");
+ die(SAMSUNG_READ_ERROR);
+ }
+
+ /* read some generic information */
+ join_path(tmp_path, output_dir, "RevisionInfo.txt");
+ rev_info_file = fopen(tmp_path, "w");
+ for (int i = 0; i < 5; i++)
+ {
+ char info[MAX_HEADER_LEN];
+ error += fgets(info, MAX_HEADER_LEN, input_file) == NULL;
+ printf("%s", info);
+ if (rev_info_file != NULL)
+ fprintf(rev_info_file, "%s", info);
+ }
+ if (rev_info_file != NULL)
+ fclose(rev_info_file);
+
+ if (error != 0)
+ {
+ fprintf(stderr, "Cannot write generic header\n");
+ die(SAMSUNG_WRITE_ERROR);
+ }
+
+ /* read metadata */
+ for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
+ {
+ char metadata[MAX_HEADER_LEN];
+ error += fgets(metadata, MAX_HEADER_LEN, input_file) == NULL;
+ error += sscanf(metadata, "%*s : size(%ld),checksum(%s)",
+ &fw.component_size[i], fw.component_checksum[i]) != 2;
+ /* strip last ")" */
+ fw.component_checksum[i][strlen(fw.component_checksum[i])-1] = '\0';
+ printf("%s: %ld bytes -- MD5 %s\n", firmware_components[i],
+ fw.component_size[i], fw.component_checksum[i]);
+ }
+
+ /* We start from the end because ROM header could have a different
+ * line count or extra new-lines (noticed in some hacked ROMs)
+ */
+ size_t current_pos = get_filesize(input_file);
+ for (int i = YPR0_COMPONENTS_COUNT-1; i >= 0; i--)
+ {
+
+ fw.component_data[i] = malloc(fw.component_size[i]);
+ current_pos -= fw.component_size[i];
+ fseek(input_file, current_pos, SEEK_SET);
+ size_t bread = fread(fw.component_data[i], 1, fw.component_size[i], input_file);
+ if (bread != fw.component_size[i])
+ fprintf(stderr, "%s: Read size mismatch: read %ld bytes, expected %ld bytes\n",
+ firmware_components[i], bread, fw.component_size[i]);
+
+ /* decrypt data */
+ cyclic_xor(fw.component_data[i], fw.component_size[i], g_yp_key, sizeof(g_yp_key));
+
+ /* unpatch bootloader */
+ if (strcmp("MBoot", firmware_components[i]) == 0)
+ {
+ memset(fw.component_data[i] + MBOOT_CHECKSUM_OFFSET, 0, MBOOT_CHECKSUM_LENGTH);
+ }
+
+ char md5sum_decrypted[MD5_DIGEST_LENGTH*2+1];
+
+ md5sum(md5sum_decrypted, fw.component_data[i], fw.component_size[i]);
+
+ if (strcmp(md5sum_decrypted, fw.component_checksum[i]) != 0)
+ {
+ printf("%s: FAIL (md5sum doesn't match)\n", firmware_components[i]);
+ md5sum_error = true;
+ }
+
+ join_path(tmp_path, output_dir, firmware_filenames[i]);
+ component_handle = fopen(tmp_path, "wb");
+
+ if (component_handle == NULL)
+ {
+ fprintf(stderr, "Error opening file for writing. Is the directory valid and writeable?\n");
+ die(SAMSUNG_WRITE_ERROR);
+ }
+
+ fwrite(fw.component_data[i], 1, fw.component_size[i], component_handle);
+ fclose(component_handle);
+
+ }
+
+ if (md5sum_error)
+ die(SAMSUNG_MD5_ERROR);
+ die(SAMSUNG_SUCCESS);
+}