blob: eb611feb37f53722ec4c73185684d6c8279b9ca9 [file] [log] [blame]
Lorenzo Miorida8a6a92013-07-09 18:20:08 +02001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2013 Lorenzo Miori
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <getopt.h>
26#include <stdint.h>
27#include <stdbool.h>
28#include "common.h"
29
30static char* output_dir = NULL;
31static FILE* input_file = NULL;
32static struct firmware_data fw;
33
34static void cleanup(void)
35{
36 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
37 {
38 free(fw.component_data[i]);
39 }
40}
41
42static void die(int error)
43{
44 if (input_file != NULL)
45 fclose(input_file);
46 free(output_dir);
47 cleanup();
48 exit(error);
49}
50
51int main(int argc, char **argv)
52{
53 FILE* component_handle = NULL;
54 FILE* rev_info_file = NULL;
55 char* tmp_path = malloc(MAX_PATH);
56 int error = 0;
57 bool md5sum_error = false;
58
59 memset(&fw, 0, sizeof(fw));
60
61 if (argc < 2)
62 {
63 printf("Decrypts Samsung YP-R0/YP-R1 ROM file format\n"
64 "Usage: fwdecrypt <ROM file path\n"
65 );
66 return 1;
67 }
68
69 output_dir = malloc(MAX_PATH);
70 output_dir[0] = '\0';
71 if (argc > 2)
72 {
73 strcpy(output_dir, argv[2]);
74 }
75
76 /* open the output file for write */
77 input_file = fopen(argv[1], "rb");
78 if (input_file == NULL)
79 {
80 fprintf(stderr, "Cannot open file for reading: %m\n");
81 die(SAMSUNG_READ_ERROR);
82 }
83
84 /* read some generic information */
85 join_path(tmp_path, output_dir, "RevisionInfo.txt");
86 rev_info_file = fopen(tmp_path, "w");
87 for (int i = 0; i < 5; i++)
88 {
89 char info[MAX_HEADER_LEN];
90 error += fgets(info, MAX_HEADER_LEN, input_file) == NULL;
91 printf("%s", info);
92 if (rev_info_file != NULL)
93 fprintf(rev_info_file, "%s", info);
94 }
95 if (rev_info_file != NULL)
96 fclose(rev_info_file);
97
98 if (error != 0)
99 {
100 fprintf(stderr, "Cannot write generic header\n");
101 die(SAMSUNG_WRITE_ERROR);
102 }
103
104 /* read metadata */
105 for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
106 {
107 char metadata[MAX_HEADER_LEN];
108 error += fgets(metadata, MAX_HEADER_LEN, input_file) == NULL;
109 error += sscanf(metadata, "%*s : size(%ld),checksum(%s)",
110 &fw.component_size[i], fw.component_checksum[i]) != 2;
111 /* strip last ")" */
112 fw.component_checksum[i][strlen(fw.component_checksum[i])-1] = '\0';
113 printf("%s: %ld bytes -- MD5 %s\n", firmware_components[i],
114 fw.component_size[i], fw.component_checksum[i]);
115 }
116
117 /* We start from the end because ROM header could have a different
118 * line count or extra new-lines (noticed in some hacked ROMs)
119 */
120 size_t current_pos = get_filesize(input_file);
121 for (int i = YPR0_COMPONENTS_COUNT-1; i >= 0; i--)
122 {
123
124 fw.component_data[i] = malloc(fw.component_size[i]);
125 current_pos -= fw.component_size[i];
126 fseek(input_file, current_pos, SEEK_SET);
127 size_t bread = fread(fw.component_data[i], 1, fw.component_size[i], input_file);
128 if (bread != fw.component_size[i])
129 fprintf(stderr, "%s: Read size mismatch: read %ld bytes, expected %ld bytes\n",
130 firmware_components[i], bread, fw.component_size[i]);
131
132 /* decrypt data */
133 cyclic_xor(fw.component_data[i], fw.component_size[i], g_yp_key, sizeof(g_yp_key));
134
135 /* unpatch bootloader */
136 if (strcmp("MBoot", firmware_components[i]) == 0)
137 {
138 memset(fw.component_data[i] + MBOOT_CHECKSUM_OFFSET, 0, MBOOT_CHECKSUM_LENGTH);
139 }
140
141 char md5sum_decrypted[MD5_DIGEST_LENGTH*2+1];
142
143 md5sum(md5sum_decrypted, fw.component_data[i], fw.component_size[i]);
144
145 if (strcmp(md5sum_decrypted, fw.component_checksum[i]) != 0)
146 {
147 printf("%s: FAIL (md5sum doesn't match)\n", firmware_components[i]);
148 md5sum_error = true;
149 }
150
151 join_path(tmp_path, output_dir, firmware_filenames[i]);
152 component_handle = fopen(tmp_path, "wb");
153
154 if (component_handle == NULL)
155 {
156 fprintf(stderr, "Error opening file for writing. Is the directory valid and writeable?\n");
157 die(SAMSUNG_WRITE_ERROR);
158 }
159
160 fwrite(fw.component_data[i], 1, fw.component_size[i], component_handle);
161 fclose(component_handle);
162
163 }
164
165 if (md5sum_error)
166 die(SAMSUNG_MD5_ERROR);
167 die(SAMSUNG_SUCCESS);
168}