mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 10:07:38 -04:00
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>
This commit is contained in:
parent
cb27d4066a
commit
da8a6a90c3
11 changed files with 621 additions and 318 deletions
|
@ -1,13 +1,20 @@
|
|||
DEFINES=
|
||||
CC=gcc
|
||||
LD=gcc
|
||||
CFLAGS=-g -std=c99 -W -Wall $(DEFINES)
|
||||
LDFLAGS=
|
||||
BINS=fwcrypt fwdecrypt
|
||||
|
||||
.PHONY: all clean
|
||||
PROGS = extract_section
|
||||
CC = gcc
|
||||
CFLAGS = -O1 -g -W -Wall
|
||||
all: $(BINS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
all: $(PROGS)
|
||||
$(MAKE) -C cramfs-1.1
|
||||
fwdecrypt: fwdecrypt.o common.o ../../tools/fwpatcher/md5.o
|
||||
$(LD) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
fwcrypt: fwcrypt.o common.o ../../tools/fwpatcher/md5.o
|
||||
$(LD) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
$(MAKE) -C cramfs-1.1 clean
|
||||
rm -f extract_section
|
||||
rm -fr *.o $(BINS)
|
||||
|
|
Binary file not shown.
|
@ -2,9 +2,9 @@
|
|||
To generate a firmware, run (paths may differ):
|
||||
|
||||
$ make
|
||||
$ ./unpack-firmware.sh R0.ROM /tmp/romfiles
|
||||
$ sudo ./patch-firmware.sh files /tmp/romfiles # needs sudo
|
||||
$ ./pack-firmware.sh R0.ROM /tmp/romfiles
|
||||
$ ./fwdecrypt R0.ROM <optional: destination path>
|
||||
$ sudo ./patch-firmware.sh files . # needs sudo
|
||||
$ ./fwcrypt R0.ROM <optional: source path>
|
||||
|
||||
After that, R0.ROM is patched and can load Rockbox.
|
||||
|
||||
|
|
94
utils/ypr0tools/common.c
Normal file
94
utils/ypr0tools/common.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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"
|
||||
#include "../../tools/fwpatcher/md5.h"
|
||||
|
||||
uint8_t g_yp_key[] =
|
||||
{
|
||||
0xa3, 0x04, 0xb9, 0xcd, 0x34, 0x13, 0x4a, 0x19, 0x19, 0x31, 0xdf, 0xbb,
|
||||
0x8f, 0x3d, 0x7f, 0x09, 0x42, 0x3c, 0x96, 0x33, 0x41, 0xa9, 0x95, 0xf1,
|
||||
0xd0, 0xac, 0x16, 0x37, 0x57, 0x35, 0x28, 0xe7, 0x0b, 0xc2, 0x12, 0x09,
|
||||
0x39, 0x42, 0xd2, 0x96, 0xf5, 0x00, 0xd2, 0x23, 0x37, 0x24, 0xe2, 0x8e,
|
||||
0x50, 0x3c, 0x6e, 0x23, 0xeb, 0x68, 0xed, 0x31, 0xb7, 0xee, 0xc0, 0xc7,
|
||||
0x09, 0xf8, 0x39, 0x9d, 0x51, 0xed, 0x17, 0x95, 0x64, 0x09, 0xe0, 0xf9,
|
||||
0xf0, 0xef, 0x86, 0xc0, 0x04, 0x46, 0x89, 0x8a, 0x6e, 0x27, 0x69, 0xde,
|
||||
0xc7, 0x31, 0x1e, 0xee, 0x3c, 0x3f, 0x17, 0x05, 0x44, 0xbb, 0xbb, 0x1d,
|
||||
0x3d, 0x5d, 0x6e, 0xf2, 0x78, 0x15, 0xd6, 0x3c, 0xcc, 0x7d, 0x67, 0x1a,
|
||||
0xb8, 0xd2, 0x79, 0x54, 0x97, 0xa2, 0x58, 0x58, 0xf7, 0x4e, 0x5e, 0x50,
|
||||
0x42, 0x69, 0xdc, 0xe7, 0x3a, 0x87, 0x2e, 0x22
|
||||
};
|
||||
|
||||
char* firmware_components[] = {"MBoot", "Linux", "RootFS", "Sysdata"};
|
||||
char* firmware_filenames[] = {"MBoot.bin", "zImage", "cramfs-fsl.rom", "SYSDATA.bin"};
|
||||
|
||||
void cyclic_xor(void *data, int datasize, void *xor, int xorsize)
|
||||
{
|
||||
for(int i = 0; i < datasize; i++)
|
||||
*(uint8_t *)(data + i) ^= *(uint8_t *)(xor + (i % xorsize));
|
||||
}
|
||||
|
||||
size_t get_filesize(FILE* handle)
|
||||
{
|
||||
long size = 0;
|
||||
long old_pos = ftell(handle);
|
||||
fseek(handle, 0, SEEK_END);
|
||||
size = ftell(handle);
|
||||
fseek(handle, old_pos, SEEK_SET);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* A very rough implementation... */
|
||||
void join_path(char* destination, char* first, char* second)
|
||||
{
|
||||
memset(destination, 0, MAX_PATH);
|
||||
if (first != NULL && strlen(first) > 0)
|
||||
{
|
||||
strcpy(destination, first);
|
||||
if (destination[strlen(destination) - 1] != DIR_SEPARATOR)
|
||||
{
|
||||
int l = strlen(destination);
|
||||
destination[l] = DIR_SEPARATOR;
|
||||
destination[l + 1] = '\0';
|
||||
}
|
||||
}
|
||||
strcat(destination, second);
|
||||
}
|
||||
|
||||
void md5sum(char* md5sum_string, char* data, unsigned long size)
|
||||
{
|
||||
uint8_t md5_checksum[16];
|
||||
md5_context c;
|
||||
md5_starts(&c);
|
||||
md5_update(&c, (unsigned char*)data, size);
|
||||
md5_finish(&c, md5_checksum);
|
||||
memset(md5sum_string, 0, MD5_DIGEST_LENGTH*2+1);
|
||||
for (int i = 0; i < MD5_DIGEST_LENGTH; i++)
|
||||
{
|
||||
sprintf(md5sum_string, "%02x", md5_checksum[i]);
|
||||
md5sum_string+=2;
|
||||
}
|
||||
}
|
86
utils/ypr0tools/common.h
Normal file
86
utils/ypr0tools/common.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
# define DIR_SEPARATOR '\\'
|
||||
#else
|
||||
# define DIR_SEPARATOR '/'
|
||||
#endif
|
||||
|
||||
#define MAX_PATH 255
|
||||
|
||||
/*
|
||||
* Firmware description
|
||||
*/
|
||||
|
||||
#define GENERIC_HEADER_LINES 5
|
||||
#define MAX_HEADER_LEN 1000
|
||||
/* Empty space used by bootloader to store checksums */
|
||||
#define MBOOT_CHECKSUM_OFFSET 96
|
||||
/* Length of the reserved space */
|
||||
#define MBOOT_CHECKSUM_LENGTH 992
|
||||
|
||||
/* In case we don't have RevisionInfo.txt file, mock values are fine */
|
||||
#define YPR0_VERSION "Version : V1.25\n"
|
||||
#define YPR0_TARGET "Target : KR\n"
|
||||
#define YPR0_USER "User : rockbox\n"
|
||||
#define YPR0_DIR "Dir : /.rockbox\n"
|
||||
#define YPR0_TIME "BuildTime : 11/04/20 14:17:34\n"
|
||||
|
||||
#define YPR0_COMPONENTS_COUNT 4
|
||||
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
|
||||
extern char* firmware_components[];
|
||||
extern char* firmware_filenames[];
|
||||
extern uint8_t g_yp_key[128];
|
||||
|
||||
struct firmware_data
|
||||
{
|
||||
char* component_data[YPR0_COMPONENTS_COUNT];
|
||||
size_t component_size[YPR0_COMPONENTS_COUNT];
|
||||
char component_checksum[YPR0_COMPONENTS_COUNT][MD5_DIGEST_LENGTH*2+1];
|
||||
};
|
||||
|
||||
enum samsung_error_t
|
||||
{
|
||||
SAMSUNG_SUCCESS = 0,
|
||||
SAMSUNG_READ_ERROR = -1,
|
||||
SAMSUNG_FORMAT_ERROR = -2,
|
||||
SAMSUNG_MD5_ERROR = -3,
|
||||
SAMSUNG_WRITE_ERROR = -4,
|
||||
};
|
||||
|
||||
void cyclic_xor(void *data, int datasize, void *xor, int xorsize);
|
||||
size_t get_filesize(FILE* handle);
|
||||
void join_path(char* destination, char* first, char* second);
|
||||
void md5sum(char* component_checksum, char* data, unsigned long size);
|
||||
|
||||
#endif /* _COMMON_H_ */
|
|
@ -1,85 +0,0 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2011 Thomas Martitz
|
||||
*
|
||||
* 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 <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* A simple replacement program for (
|
||||
* dd if=$file1 of=$file2 bs=1 skip=$offset count=$size
|
||||
*
|
||||
* Written because byte-size operations with dd are unbearably slow.
|
||||
*/
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: extract_section <romfile> <outfile> <offset> <byte count>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void die(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
if (argc != 5)
|
||||
usage();
|
||||
|
||||
int ifd, ofd;
|
||||
ssize_t size = atol(argv[4]);
|
||||
long skip = atol(argv[3]);
|
||||
|
||||
if (!size)
|
||||
die("invalid byte count\n");
|
||||
|
||||
ifd = open(argv[1], O_RDONLY);
|
||||
if (ifd < 0)
|
||||
die("Could not open %s for reading!\n", argv[1]);
|
||||
|
||||
ofd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if (ofd < 0)
|
||||
die("Could not create %s\n", argv[2]);
|
||||
|
||||
void *buf = malloc(size);
|
||||
if (!buf) die("OOM\n");
|
||||
|
||||
lseek(ifd, skip, SEEK_SET);
|
||||
lseek(ofd, 0, SEEK_SET);
|
||||
if (read(ifd, buf, size) != size)
|
||||
die("Read failed\n");
|
||||
if (write(ofd, buf, size) != size)
|
||||
die("write failed\n");
|
||||
|
||||
close(ifd);
|
||||
close(ofd);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
170
utils/ypr0tools/fwcrypt.c
Normal file
170
utils/ypr0tools/fwcrypt.c
Normal file
|
@ -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);
|
||||
}
|
168
utils/ypr0tools/fwdecrypt.c
Normal file
168
utils/ypr0tools/fwdecrypt.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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 <stdbool.h>
|
||||
#include "common.h"
|
||||
|
||||
static char* output_dir = NULL;
|
||||
static FILE* input_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 (input_file != NULL)
|
||||
fclose(input_file);
|
||||
free(output_dir);
|
||||
cleanup();
|
||||
exit(error);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE* component_handle = NULL;
|
||||
FILE* rev_info_file = NULL;
|
||||
char* tmp_path = malloc(MAX_PATH);
|
||||
int error = 0;
|
||||
bool md5sum_error = false;
|
||||
|
||||
memset(&fw, 0, sizeof(fw));
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Decrypts Samsung YP-R0/YP-R1 ROM file format\n"
|
||||
"Usage: fwdecrypt <ROM file path\n"
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
output_dir = malloc(MAX_PATH);
|
||||
output_dir[0] = '\0';
|
||||
if (argc > 2)
|
||||
{
|
||||
strcpy(output_dir, argv[2]);
|
||||
}
|
||||
|
||||
/* open the output file for write */
|
||||
input_file = fopen(argv[1], "rb");
|
||||
if (input_file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot open file for reading: %m\n");
|
||||
die(SAMSUNG_READ_ERROR);
|
||||
}
|
||||
|
||||
/* read some generic information */
|
||||
join_path(tmp_path, output_dir, "RevisionInfo.txt");
|
||||
rev_info_file = fopen(tmp_path, "w");
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
char info[MAX_HEADER_LEN];
|
||||
error += fgets(info, MAX_HEADER_LEN, input_file) == NULL;
|
||||
printf("%s", info);
|
||||
if (rev_info_file != NULL)
|
||||
fprintf(rev_info_file, "%s", info);
|
||||
}
|
||||
if (rev_info_file != NULL)
|
||||
fclose(rev_info_file);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
fprintf(stderr, "Cannot write generic header\n");
|
||||
die(SAMSUNG_WRITE_ERROR);
|
||||
}
|
||||
|
||||
/* read metadata */
|
||||
for (int i = 0; i < YPR0_COMPONENTS_COUNT; i++)
|
||||
{
|
||||
char metadata[MAX_HEADER_LEN];
|
||||
error += fgets(metadata, MAX_HEADER_LEN, input_file) == NULL;
|
||||
error += sscanf(metadata, "%*s : size(%ld),checksum(%s)",
|
||||
&fw.component_size[i], fw.component_checksum[i]) != 2;
|
||||
/* strip last ")" */
|
||||
fw.component_checksum[i][strlen(fw.component_checksum[i])-1] = '\0';
|
||||
printf("%s: %ld bytes -- MD5 %s\n", firmware_components[i],
|
||||
fw.component_size[i], fw.component_checksum[i]);
|
||||
}
|
||||
|
||||
/* We start from the end because ROM header could have a different
|
||||
* line count or extra new-lines (noticed in some hacked ROMs)
|
||||
*/
|
||||
size_t current_pos = get_filesize(input_file);
|
||||
for (int i = YPR0_COMPONENTS_COUNT-1; i >= 0; i--)
|
||||
{
|
||||
|
||||
fw.component_data[i] = malloc(fw.component_size[i]);
|
||||
current_pos -= fw.component_size[i];
|
||||
fseek(input_file, current_pos, SEEK_SET);
|
||||
size_t bread = fread(fw.component_data[i], 1, fw.component_size[i], input_file);
|
||||
if (bread != fw.component_size[i])
|
||||
fprintf(stderr, "%s: Read size mismatch: read %ld bytes, expected %ld bytes\n",
|
||||
firmware_components[i], bread, fw.component_size[i]);
|
||||
|
||||
/* decrypt data */
|
||||
cyclic_xor(fw.component_data[i], fw.component_size[i], g_yp_key, sizeof(g_yp_key));
|
||||
|
||||
/* unpatch bootloader */
|
||||
if (strcmp("MBoot", firmware_components[i]) == 0)
|
||||
{
|
||||
memset(fw.component_data[i] + MBOOT_CHECKSUM_OFFSET, 0, MBOOT_CHECKSUM_LENGTH);
|
||||
}
|
||||
|
||||
char md5sum_decrypted[MD5_DIGEST_LENGTH*2+1];
|
||||
|
||||
md5sum(md5sum_decrypted, fw.component_data[i], fw.component_size[i]);
|
||||
|
||||
if (strcmp(md5sum_decrypted, fw.component_checksum[i]) != 0)
|
||||
{
|
||||
printf("%s: FAIL (md5sum doesn't match)\n", firmware_components[i]);
|
||||
md5sum_error = true;
|
||||
}
|
||||
|
||||
join_path(tmp_path, output_dir, firmware_filenames[i]);
|
||||
component_handle = fopen(tmp_path, "wb");
|
||||
|
||||
if (component_handle == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error opening file for writing. Is the directory valid and writeable?\n");
|
||||
die(SAMSUNG_WRITE_ERROR);
|
||||
}
|
||||
|
||||
fwrite(fw.component_data[i], 1, fw.component_size[i], component_handle);
|
||||
fclose(component_handle);
|
||||
|
||||
}
|
||||
|
||||
if (md5sum_error)
|
||||
die(SAMSUNG_MD5_ERROR);
|
||||
die(SAMSUNG_SUCCESS);
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
######################################################################
|
||||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
#
|
||||
# * Script to generate a Samsung YP-R0 firmware file (R0.ROM) */
|
||||
######################################################################
|
||||
#
|
||||
# This file was oringally called NewPack.sh, its origin is the R0 open source
|
||||
# package from Samsung.
|
||||
#
|
||||
# Muon Platform
|
||||
# Copyright (c) 2004-2009 Samsung Electronics, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Rom Packaging Script
|
||||
# It needs sudoer privilege of rm, mkdir, cp, mkcramfs.
|
||||
# You can configure it in the /etc/sudoer file.
|
||||
# This script is very dangerous. Be careful to use.
|
||||
#
|
||||
# SangMan Sim<sangman.sim@samsung.com>
|
||||
|
||||
# bail out early
|
||||
set -e
|
||||
|
||||
DIR=${2:-"."}
|
||||
DIR=${DIR%/}
|
||||
REVISION="$DIR/RevisionInfo.txt"
|
||||
CRAMFS="$DIR/cramfs-fsl.rom"
|
||||
SYSDATA="$DIR/SYSDATA.bin"
|
||||
MBOOT="$DIR/MBoot.bin"
|
||||
MBOOT_TMP="${TMP_DIR:-$DIR}/MBoot.tmp"
|
||||
LINUX="$DIR/zImage"
|
||||
R0ROM=$1
|
||||
|
||||
# some sanity checks
|
||||
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
|
||||
echo "Usage $0 <rom file> [path to image files]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f ./MuonEncrypt ]; then
|
||||
echo "Couldn't find MuonEncrypt binary (try 'make')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e $REVISION ]; then
|
||||
cat >$REVISION <<EOF
|
||||
Version : V2.30
|
||||
Target : KR
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
||||
function WriteImage {
|
||||
echo "Adding $1 to $R0ROM"
|
||||
#HEAD_STR=[`stat -c%s $1`/`md5sum $1 | cut -d " " -f 1`]
|
||||
#HEAD_SIZE=`echo $HEAD_STR | wc -c`
|
||||
#PACK_SIZE=`expr 44 - $HEAD_SIZE`
|
||||
|
||||
#while [ $PACK_SIZE -gt 0 ]
|
||||
#do
|
||||
#PACK_SIZE=`expr $PACK_SIZE - 1`
|
||||
#echo -n 0
|
||||
#done
|
||||
|
||||
./MuonEncrypt $1 >> $R0ROM
|
||||
#cat $MBOOT >> $R0ROM
|
||||
}
|
||||
|
||||
function Pack4Byte {
|
||||
FILE_SIZE=`stat -c%s $R0ROM`
|
||||
PACK_SIZE=`expr 4 - $FILE_SIZE % 4`
|
||||
|
||||
if [ $PACK_SIZE != 4 ]
|
||||
then
|
||||
while [ $PACK_SIZE -gt 0 ]
|
||||
do
|
||||
PACK_SIZE=`expr $PACK_SIZE - 1` || true
|
||||
echo -en $1 >> $R0ROM
|
||||
done
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
echo Make $R0ROM
|
||||
|
||||
cat $REVISION > $R0ROM
|
||||
echo User : $USER >> $R0ROM
|
||||
echo Dir : $PWD >> $R0ROM
|
||||
echo BuildTime : `date "+%y/%m/%d %H:%M:%S"` >> $R0ROM
|
||||
echo MBoot : size\(`stat -c%s $MBOOT`\),checksum\(`md5sum $MBOOT | cut -d " " -f 1`\) >> $R0ROM
|
||||
echo Linux : size\(`stat -c%s $LINUX`\),checksum\(`md5sum $LINUX | cut -d " " -f 1`\) >> $R0ROM
|
||||
echo RootFS : size\(`stat -c%s $CRAMFS`\),checksum\(`md5sum $CRAMFS | cut -d " " -f 1`\) >> $R0ROM
|
||||
echo Sysdata : size\(`stat -c%s $SYSDATA`\),checksum\(`md5sum $SYSDATA | cut -d " " -f 1`\) >> $R0ROM
|
||||
|
||||
Pack4Byte "\\n"
|
||||
|
||||
|
||||
dd if=$MBOOT of=$MBOOT_TMP bs=96 count=1 2> /dev/null
|
||||
|
||||
echo `stat -c%s $MBOOT`:`md5sum $MBOOT | cut -d " " -f 1` >> $MBOOT_TMP
|
||||
echo `stat -c%s $LINUX`:`md5sum $LINUX | cut -d " " -f 1` >> $MBOOT_TMP
|
||||
echo `stat -c%s $CRAMFS`:`md5sum $CRAMFS | cut -d " " -f 1` >> $MBOOT_TMP
|
||||
echo `stat -c%s $SYSDATA`:`md5sum $SYSDATA | cut -d " " -f 1` >> $MBOOT_TMP
|
||||
|
||||
dd if=$MBOOT of=$MBOOT_TMP bs=1088 skip=1 seek=1 2> /dev/null
|
||||
WriteImage $MBOOT_TMP
|
||||
|
||||
#rm $MBOOT_TMP
|
||||
|
||||
Pack4Byte "0"
|
||||
|
||||
WriteImage $LINUX
|
||||
|
||||
Pack4Byte "0"
|
||||
|
||||
WriteImage $CRAMFS
|
||||
|
||||
Pack4Byte "0"
|
||||
|
||||
WriteImage $SYSDATA
|
||||
|
||||
echo $R0ROM : `stat -c%s $R0ROM`, `md5sum $R0ROM | cut -d " " -f 1`
|
||||
#head -9 $R0ROM
|
||||
|
||||
echo "Done"
|
85
utils/ypr0tools/test.sh
Executable file
85
utils/ypr0tools/test.sh
Executable file
|
@ -0,0 +1,85 @@
|
|||
#!/bin/sh
|
||||
|
||||
######################################################################
|
||||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
#
|
||||
# Script to test packer and unpacker
|
||||
# Copyright (C) 2013 Lorenzo Miori
|
||||
######################################################################
|
||||
|
||||
ROM_FILE="$1"
|
||||
TMP_FOLDER=""
|
||||
|
||||
goto_temp()
|
||||
{
|
||||
if [ -n "$TMP_FOLDER" ]
|
||||
then
|
||||
cd $TMP_FOLDER
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
echo "$1"
|
||||
OLD_DIR=`pwd`
|
||||
goto_temp
|
||||
rm -f "$ROM_FILE"_TEST_CRYPT "MBoot.bin" "zImage" "cramfs-fsl.rom" "SYSDATA.bin" "TEST_MD5SUMS" "RevisionInfo.txt" > /dev/null
|
||||
cd $OLD_DIR
|
||||
if [ -n "$TMP_FOLDER" ]
|
||||
then
|
||||
rmdir $TMP_FOLDER
|
||||
fi
|
||||
make clean
|
||||
exit $2
|
||||
}
|
||||
|
||||
if [ $# -lt 1 ]
|
||||
then
|
||||
cleanup "FAIL: Missing parameter! Run with: test.sh <path to working rom to test> <optional: destination to temporary files>" 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 2 ]
|
||||
then
|
||||
TMP_FOLDER="$2/"
|
||||
mkdir $TMP_FOLDER
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "FAIL: temporary directory exists!"
|
||||
fi
|
||||
fi
|
||||
|
||||
# be sure we have the executables up-to-date
|
||||
make clean
|
||||
make
|
||||
|
||||
./fwdecrypt $1 $TMP_FOLDER
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
cleanup "FAIL: Error while decrypting ROM file" 1
|
||||
fi
|
||||
|
||||
./fwcrypt $TMP_FOLDER$1_TEST_CRYPT $TMP_FOLDER
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
cleanup "FAIL: Error while decrypting ROM file" 1
|
||||
fi
|
||||
|
||||
OLD_DIR=`pwd`
|
||||
goto_temp
|
||||
|
||||
md5sum MBoot.bin zImage cramfs-fsl.rom SYSDATA.bin RevisionInfo.txt > "TEST_MD5SUMS"
|
||||
|
||||
md5sum --strict -c "TEST_MD5SUMS"
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
cleanup "FAIL: MD5SUM mismatch!" 1
|
||||
fi
|
||||
|
||||
cd $OLD_DIR
|
||||
|
||||
cleanup "OK: test completed without errors." 0
|
|
@ -1,90 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
######################################################################
|
||||
# __________ __ ___.
|
||||
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
# \/ \/ \/ \/ \/
|
||||
#
|
||||
# * Script to unpack a Samsung YP-R0 firmware file (R0.ROM) */
|
||||
######################################################################
|
||||
|
||||
# The file was originally called MuonDecrypt.sh
|
||||
#
|
||||
# I'm not sure about the original author of this file, as it wasn't included in Samsung package.
|
||||
# But I guess it was done by JeanLouis, an Italian user of the Hardware Upgrade Forum. If needed, we should search throug old posts for that...
|
||||
#
|
||||
|
||||
|
||||
# bail out early
|
||||
set -e
|
||||
|
||||
# some sanity checks
|
||||
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
|
||||
echo "Usage $0 <rom file> [out dir]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
ROM=$1
|
||||
DIR=${2:-"."}
|
||||
DIR=${DIR%/}
|
||||
MBOOT="$DIR/MBoot.bin"
|
||||
MBOOT_TMP="${TMP_DIR:-$DIR}/MBoot.tmp"
|
||||
LINUX="$DIR/zImage"
|
||||
CRAMFS="$DIR/cramfs-fsl.rom"
|
||||
SYSDATA="$DIR/SYSDATA.bin"
|
||||
MD5SUMS="$DIR/MD5SUMS"
|
||||
TMP="${TMP_DIR:-$DIR}/_$$.tmp"
|
||||
|
||||
|
||||
if [ ! -f ./extract_section ]; then
|
||||
echo "Couldn't find extract_section binary (try 'make')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f ./MuonEncrypt ]; then
|
||||
echo "Couldn't find MuonEncrypt binary (try 'make')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $DIR
|
||||
|
||||
if [ ! -w $DIR ]; then
|
||||
echo "Target dir not writable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ExtractAndDecrypt() {
|
||||
START=$(expr $START - $2)
|
||||
echo "Extracting $1..."
|
||||
./extract_section $ROM $TMP $START $2
|
||||
echo "Decrypt $1..."
|
||||
./MuonEncrypt $TMP > $1
|
||||
}
|
||||
|
||||
size=( `head -n 9 $ROM | tail -n 4 | while read LINE; do echo $LINE | cut -d\( -f 2 | cut -d\) -f 1; done`)
|
||||
checksum=( `head -n 9 $ROM | tail -n 4 | while read LINE; do echo $LINE | cut -d\( -f 3 | cut -d\) -f 1; done`)
|
||||
|
||||
echo "${checksum[0]} $MBOOT" > $MD5SUMS
|
||||
echo "${checksum[1]} $LINUX" >> $MD5SUMS
|
||||
echo "${checksum[2]} $CRAMFS" >> $MD5SUMS
|
||||
echo "${checksum[3]} $SYSDATA" >> $MD5SUMS
|
||||
|
||||
START=`stat -c%s $ROM`
|
||||
|
||||
ExtractAndDecrypt $SYSDATA ${size[3]}
|
||||
ExtractAndDecrypt $CRAMFS ${size[2]}
|
||||
ExtractAndDecrypt $LINUX ${size[1]}
|
||||
ExtractAndDecrypt $MBOOT_TMP ${size[0]}
|
||||
|
||||
rm $TMP
|
||||
echo "Create $MBOOT..."
|
||||
dd if=$MBOOT_TMP of=$MBOOT bs=96 count=1 2>/dev/null
|
||||
dd if=$MBOOT_TMP of=$MBOOT bs=1088 skip=1 seek=1 2>/dev/null
|
||||
rm $MBOOT_TMP
|
||||
|
||||
echo "Check integrity:"
|
||||
md5sum -c $MD5SUMS
|
Loading…
Add table
Add a link
Reference in a new issue