rockbox/utils/ypr0tools/fwcrypt.c
Lorenzo Miori da8a6a90c3 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>
2013-09-07 15:56:07 +02:00

170 lines
5.6 KiB
C

/***************************************************************************
* __________ __ ___.
* 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);
}