diff options
Diffstat (limited to 'utils/ypr0tools/fwcrypt.c')
-rw-r--r-- | utils/ypr0tools/fwcrypt.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/utils/ypr0tools/fwcrypt.c b/utils/ypr0tools/fwcrypt.c new file mode 100644 index 0000000000..e99d8872ba --- /dev/null +++ b/utils/ypr0tools/fwcrypt.c @@ -0,0 +1,170 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "common.h" + +static char* input_dir = NULL; +static FILE* output_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 (output_file != NULL) + fclose(output_file); + free(input_dir); + cleanup(); + exit(error); +} + +int main(int argc, char **argv) +{ + FILE* component_handle = NULL; + FILE* rev_info_file = NULL; + int error = 0; + char* tmp_path = malloc(MAX_PATH); + + memset(&fw, 0, sizeof(fw)); + + if (argc < 2) + { + printf( + "Crypts Samsung YP-R0/YP-R1 ROM file format\n" + "Usage: fwcrypt <output ROM file path\n" + ); + return 1; + } + + input_dir = malloc(MAX_PATH); + input_dir[0] = '\0'; + if (argc > 2) + { + strcpy(input_dir, argv[2]); + } + + /* open the output file for write */ + output_file = fopen(argv[1], "wb"); + if (output_file == NULL) + { + fprintf(stderr, "Cannot open file for writing: %m\n"); + die(SAMSUNG_WRITE_ERROR); + } + + /* write generic header */ + join_path(tmp_path, input_dir, "RevisionInfo.txt"); + rev_info_file = fopen(tmp_path, "rb"); + if (rev_info_file != NULL) + { + for (int i = 0; i < GENERIC_HEADER_LINES; i++) + { + char header[MAX_HEADER_LEN]; + error += fgets(header, MAX_HEADER_LEN, rev_info_file) == NULL; + error += fprintf(output_file, "%s", header) != (signed)strlen(header); + } + fclose(rev_info_file); + } + else + { + /* write some generic information */ + error += fprintf(output_file, YPR0_VERSION) != strlen(YPR0_VERSION); + error += fprintf(output_file, YPR0_TARGET) != strlen(YPR0_TARGET); + error += fprintf(output_file, YPR0_USER) != strlen(YPR0_USER); + error += fprintf(output_file, YPR0_DIR) != strlen(YPR0_DIR); + error += fprintf(output_file, YPR0_TIME) != strlen(YPR0_TIME); + } + + if(error != 0) + { + fprintf(stderr, "Cannot write generic header\n"); + die(SAMSUNG_WRITE_ERROR); + } + + for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++) + { + join_path(tmp_path, input_dir, firmware_filenames[i]); + component_handle = fopen(tmp_path, "rb"); + if (component_handle == NULL) + { + fprintf(stderr, "Error while reading firmware component.\n"); + die(SAMSUNG_READ_ERROR); + } + fw.component_size[i] = get_filesize(component_handle); + fw.component_data[i] = malloc(fw.component_size[i] * sizeof(char)); + fread(fw.component_data[i], sizeof(char), fw.component_size[i], component_handle); + fclose(component_handle); + + /* compute checksum */ + md5sum(fw.component_checksum[i], fw.component_data[i], fw.component_size[i]); + printf("%s : size(%ld),checksum(%s)\n", firmware_components[i], + fw.component_size[i], fw.component_checksum[i]); + /* write metadata header to file */ + if (fprintf(output_file, "%s : size(%ld),checksum(%s)\n", firmware_components[i], + fw.component_size[i], fw.component_checksum[i]) < 0) + { + fprintf(stderr, "Error writing to output file.\n"); + die(SAMSUNG_WRITE_ERROR); + } + } + + /* write final data to the firmware file */ + for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++) + { + /* the bootloader needs to be patched: add checksum of the components */ + if (strcmp("MBoot", firmware_components[i]) == 0) + { + int index=MBOOT_CHECKSUM_OFFSET; + for (int z = 0; z < YPR0_COMPONENTS_COUNT; z++) + { + index += sprintf(fw.component_data[i] + index, "%ld:%s\n", + fw.component_size[z], fw.component_checksum[z]); + } + } + /* crypt data */ + cyclic_xor(fw.component_data[i], fw.component_size[i], g_yp_key, sizeof(g_yp_key)); + /* write data */ + size_t written = fwrite(fw.component_data[i], sizeof(char), + fw.component_size[i], output_file); + if (written != fw.component_size[i]) + { + fprintf(stderr, "%s: error writing data to file. Written %ld bytes\n", + firmware_components[i], written); + die(SAMSUNG_WRITE_ERROR); + } + /* padding */ + if (i < (YPR0_COMPONENTS_COUNT-1)) + fputs("\0\0\0\0", output_file); + } + + /* free the big amount of memory and close handles */ + die(SAMSUNG_SUCCESS); +} |