5ef1e2dcfa
fixed a bug concerning bytes padding, since it wasn't correctly implemented regarding original firmware structure. This fixes ROM generation especially for ypr1. Change-Id: I1a40fb4bb8f9d6b005d694246123e314c4d19b49 Reviewed-on: http://gerrit.rockbox.org/616 Reviewed-by: Thomas Martitz <kugel@rockbox.org>
182 lines
5.8 KiB
C
182 lines
5.8 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);
|
|
}
|
|
|
|
static void pad4byte(char byte, FILE* handle) {
|
|
int padding = 4 - ftell(handle) % 4;
|
|
if (padding != 4) {
|
|
while (padding-- > 0) {
|
|
fwrite(&byte, 1, 1, handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/* Padding */
|
|
pad4byte('\n', output_file);
|
|
|
|
/* 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))
|
|
pad4byte('\0', output_file);
|
|
}
|
|
|
|
/* free the big amount of memory and close handles */
|
|
die(SAMSUNG_SUCCESS);
|
|
}
|