blob: f920406e12410669f12a0d11f3edd537322411b6 [file] [log] [blame]
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 Amaury Pouly
*
* 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 "samsung.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <getopt.h>
#include <string.h>
static bool g_debug = false;
static char *g_out_prefix = NULL;
static void usage(void)
{
printf("Usage: fwcrypt [options] content\n");
printf("Options:\n");
printf(" -o <prefix>\tSet output file\n");
printf(" -m/--model <model>\tSet model\n");
printf(" -v/--version <ver>\tSet version\n");
printf(" -r/--region <region>\tSet region\n");
printf(" -e/--extra <extra>\tSet extra\n");
printf(" -?/--help\tDisplay this message\n");
printf(" -d/--debug\tDisplay debug messages\n");
exit(1);
}
static int s_write(void *user, int offset, void *buf, int size)
{
FILE *f = user;
if(fseek(f, offset, SEEK_SET) != 0)
return 0;
return fwrite(buf, 1, size, f);
}
static void s_printf(void *user, bool error, const char *fmt, ...)
{
if(!g_debug && !error)
return;
(void) user;
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(int argc, char **argv)
{
struct samsung_firmware_t *fw = malloc(sizeof(struct samsung_firmware_t));
memset(fw, 0, sizeof(struct samsung_firmware_t));
if(argc <= 1)
usage();
while(1)
{
static struct option long_options[] =
{
{"help", no_argument, 0, '?'},
{"debug", no_argument, 0, 'd'},
{"model", required_argument, 0, 'm'},
{"version", required_argument, 0, 'v'},
{"region", required_argument, 0, 'r'},
{"extra", required_argument, 0, 'e'},
{0, 0, 0, 0}
};
int c = getopt_long(argc, argv, "?do:m:v:r:e:", long_options, NULL);
if(c == -1)
break;
switch(c)
{
case -1:
break;
case 'd':
g_debug = true;
break;
case '?':
usage();
break;
case 'o':
g_out_prefix = optarg;
break;
case 'm':
strncpy(fw->model, optarg, sizeof(fw->model));
if(strlen(optarg) > sizeof(fw->model))
printf("Warning: truncate model string\n");
break;
case 'r':
strncpy(fw->region, optarg, sizeof(fw->region));
if(strlen(optarg) > sizeof(fw->region))
printf("Warning: truncate region string\n");
break;
case 'v':
strncpy(fw->version, optarg, sizeof(fw->version));
if(strlen(optarg) > sizeof(fw->version))
printf("Warning: truncate vesion string\n");
break;
case 'e':
strncpy(fw->extra, optarg, sizeof(fw->extra));
if(strlen(optarg) > sizeof(fw->extra))
printf("Warning: truncate extra string\n");
break;
default:
abort();
}
}
if(optind != argc - 1)
usage();
FILE *fin = fopen(argv[optind], "rb");
if(fin == NULL)
{
printf("Cannot open file for reading: %m\n");
samsung_free(fw);
return 1;
}
fseek(fin, 0, SEEK_END);
fw->data_size = ftell(fin);
fseek(fin, 0, SEEK_SET);
fw->data = malloc(fw->data_size);
if((int)fread(fw->data, 1, fw->data_size, fin) != fw->data_size)
{
printf("Cannot read input file: %m\n");
samsung_free(fw);
return 2;
}
fclose(fin);
if(g_out_prefix)
{
FILE *f = fopen(g_out_prefix, "wb");
if(f == NULL)
{
printf("Cannot open file for writing: %m\n");
samsung_free(fw);
return 1;
}
enum samsung_error_t err = samsung_write(s_write, s_printf, f, fw);
if(err != SAMSUNG_SUCCESS)
{
printf("Error writing firmware: %d\n", err);
samsung_free(fw);
return 3;
}
fclose(f);
}
samsung_free(fw);
return 0;
}