From c876d3bbefe0dc00c27ca0c12d29da5874946962 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Wed, 15 Dec 2021 21:04:28 +0100 Subject: rbutil: Merge rbutil with utils folder. rbutil uses several components from the utils folder, and can be considered part of utils too. Having it in a separate folder is an arbitrary split that doesn't help anymore these days, so merge them. This also allows other utils to easily use libtools.make without the need to navigate to a different folder. Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21 --- utils/mktccboot/Makefile | 28 +++++++ utils/mktccboot/README | 35 +++++++++ utils/mktccboot/main.c | 133 +++++++++++++++++++++++++++++++++ utils/mktccboot/mktccboot.c | 176 ++++++++++++++++++++++++++++++++++++++++++++ utils/mktccboot/mktccboot.h | 50 +++++++++++++ 5 files changed, 422 insertions(+) create mode 100644 utils/mktccboot/Makefile create mode 100644 utils/mktccboot/README create mode 100644 utils/mktccboot/main.c create mode 100644 utils/mktccboot/mktccboot.c create mode 100644 utils/mktccboot/mktccboot.h (limited to 'utils/mktccboot') diff --git a/utils/mktccboot/Makefile b/utils/mktccboot/Makefile new file mode 100644 index 0000000000..4943a8c568 --- /dev/null +++ b/utils/mktccboot/Makefile @@ -0,0 +1,28 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +# We use the Telechips code available in the Rockbox tools/ directory +TOOLSDIR = ../../tools/ +CFLAGS += -O -g -W -Wall -Wshadow -pedantic -I$(TOOLSDIR) + +OUTPUT = mktccboot + + +# inputs +LIBSOURCES := mktccboot.c $(TOOLSDIR)telechips.c +SOURCES := main.c +EXTRADEPS := + +include ../libtools.make + +# rule for sources from tools dir +# Rules go _after_ including mkboot.make to have OBJDIR set up correctly. +# Paths are assumed to end with a / +telechips.o: $(OBJDIR)telechips.o + diff --git a/utils/mktccboot/README b/utils/mktccboot/README new file mode 100644 index 0000000000..719846f2e8 --- /dev/null +++ b/utils/mktccboot/README @@ -0,0 +1,35 @@ +mktccboot +--------- + +A tool to inject a bootloader into a Telechips 77X/78X firmware file. + +Usage +----- + +mktccboot + + is an original Telechips firmware file. + + is the code you want to execute (a rockbox bootloader), previously + scrambled with tools/scramble utility. + + is the resulting firmware file which you'll have to copy on your + player. See "Firmware filenames". + +Dual-Boot +--------- + +The purpose of this program is to provide dual-boot between the original +firmware and the new (rockbox) firmware. + +By default the player will boot into the new firmware. + +To boot into the Original Firmware, you need to press the key. + +The player will boot into the Original Firmware as well if it is powered up by +inserting an usb cable. + +Hacking +------- + +See comments in mktccboot.c for more information. diff --git a/utils/mktccboot/main.c b/utils/mktccboot/main.c new file mode 100644 index 0000000000..4dd5d0c6c4 --- /dev/null +++ b/utils/mktccboot/main.c @@ -0,0 +1,133 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 by Dave Chapman + * + * Based on mkboot, Copyright (C) 2005 by Linus Nielsen Feltzing + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "mktccboot.h" +#include "telechips.h" + +static void usage(void) +{ + printf("Usage: mktccboot \n"); + + exit(1); +} + +int main(int argc, char *argv[]) +{ + char *infile, *bootfile, *outfile; + int fdout = -1; + int n, of_size, boot_size, patched_size; + unsigned char *of_buf; + unsigned char *boot_buf = NULL; + unsigned char* image = NULL; + int ret = 0; + + if(argc < 3) { + usage(); + } + + infile = argv[1]; + bootfile = argv[2]; + outfile = argv[3]; + + /* Read OF and boot files */ + of_buf = file_read(infile, &of_size); + if (!of_buf) + { + ret = 1; + goto error_exit; + } + + /* Validate input file */ + if (test_firmware_tcc(of_buf, of_size)) + { + printf("[ERR] Unknown OF file used, aborting\n"); + ret = 2; + goto error_exit; + } + + boot_buf = file_read(bootfile, &boot_size); + if (!boot_buf) + { + ret = 3; + goto error_exit; + } + + /* Allocate buffer for patched firmware */ + image = malloc(of_size + boot_size); + if (image == NULL) + { + printf("[ERR] Could not allocate memory, aborting\n"); + ret = 4; + goto error_exit; + } + + /* Create the patched firmware */ + image = patch_firmware_tcc(of_buf, of_size, boot_buf, boot_size, + &patched_size); + if (!image) + { + printf("[ERR] Error creating patched firmware, aborting\n"); + ret = 5; + goto error_exit; + } + + fdout = open(outfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644); + if (fdout < 0) + { + perror(outfile); + ret = 6; + goto error_exit; + } + + n = write(fdout, image, patched_size); + if (n != patched_size) + { + printf("[ERR] Could not write output file %s\n",outfile); + ret = 7; + goto error_exit; + } + +error_exit: + + if (fdout >= 0) + close(fdout); + + if (of_buf) + free(of_buf); + + if (boot_buf) + free(boot_buf); + + if (image) + free(image); + + return ret; +} + diff --git a/utils/mktccboot/mktccboot.c b/utils/mktccboot/mktccboot.c new file mode 100644 index 0000000000..4f2c3258db --- /dev/null +++ b/utils/mktccboot/mktccboot.c @@ -0,0 +1,176 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 by Dave Chapman + * + * Based on mkboot, Copyright (C) 2005 by Linus Nielsen Feltzing + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "mktccboot.h" +#include "telechips.h" + +/* + +Append a Rockbox bootloader to a Telechips original firmware file. + +The first instruction in a TCC firmware file is always of the form: + + ldr pc, [pc, #xxx] + +where [pc, #xxx] is the entry point of the firmware - e.g. 0x20000020 + +mktccboot appends the Rockbox bootloader to the end of the original +firmware image and replaces the contents of [pc, #xxx] with the entry +point of our bootloader - i.e. the length of the original firmware plus +0x20000000. + +It then stores the original entry point from [pc, #xxx] in a fixed +offset in the Rockbox boootloader, which is used by the bootloader to +dual-boot. + +Finally, mktccboot corrects the length and CRCs in the main firmware +header, creating a new legal firmware file which can be installed on +the device. + +*/ + +/* win32 compatibility */ + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +static void put_uint32le(uint32_t x, unsigned char* p) +{ + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +static uint32_t get_uint32le(unsigned char* p) +{ + return (p[3] << 24) | (p[2] << 16) | (p[1]<<8) | p[0]; +} + +static off_t filesize(int fd) { + struct stat buf; + + if (fstat(fd,&buf) < 0) { + perror("[ERR] Checking filesize of input file"); + return -1; + } else { + return(buf.st_size); + } +} + +#define DRAMORIG 0x20000000 +/* Injects a bootloader into a Telechips 77X/78X firmware file */ +unsigned char *patch_firmware_tcc(unsigned char *of_buf, int of_size, + unsigned char *boot_buf, int boot_size, int *patched_size) +{ + unsigned char *patched_buf; + uint32_t ldr, old_ep_offset, new_ep_offset; + int of_offset; + + patched_buf = malloc(of_size + boot_size); + if (!patched_buf) + return NULL; + + memcpy(patched_buf, of_buf, of_size); + memcpy(patched_buf + of_size, boot_buf, boot_size); + + ldr = get_uint32le(patched_buf); + + /* TODO: Verify it's a LDR instruction */ + of_offset = (ldr & 0xfff) + 8; + old_ep_offset = get_uint32le(patched_buf + of_offset); + new_ep_offset = DRAMORIG + of_size; + + printf("OF entry point: 0x%08x\n", old_ep_offset); + printf("New entry point: 0x%08x\n", new_ep_offset + 8); + + /* Save the OF entry point at the start of the bootloader image */ + put_uint32le(old_ep_offset, patched_buf + of_size); + put_uint32le(new_ep_offset, patched_buf + of_size + 4); + + /* Change the OF entry point to the third word in our bootloader */ + put_uint32le(new_ep_offset + 8, patched_buf + of_offset); + + telechips_encode_crc(patched_buf, of_size + boot_size); + *patched_size = of_size + boot_size; + + return patched_buf; +} + +unsigned char *file_read(char *filename, int *size) +{ + unsigned char *buf = NULL; + int n, fd = -1; + + /* Open file for reading */ + fd = open(filename, O_RDONLY|O_BINARY); + if (fd < 0) + { + printf("[ERR] Could open file for reading, aborting\n"); + perror(filename); + goto error; + } + + /* Get file size, and allocate a buffer of that size */ + *size = filesize(fd); + buf = malloc(*size); + if (buf == NULL) + { + printf("[ERR] Could not allocate memory, aborting\n"); + goto error; + } + + /* Read the file's content to the buffer */ + n = read(fd, buf, *size); + if (n != *size) + { + printf("[ERR] Could not read from %s\n", filename); + goto error; + } + + return buf; + +error: + if (fd >= 0) + close(fd); + + if (buf) + free(buf); + + return NULL; +} + +/* A CRC test in order to reject non OF file */ +int test_firmware_tcc(unsigned char* buf, int length) +{ + return telechips_test_crc(buf, length); +} + diff --git a/utils/mktccboot/mktccboot.h b/utils/mktccboot/mktccboot.h new file mode 100644 index 0000000000..17179c11e7 --- /dev/null +++ b/utils/mktccboot/mktccboot.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * mktccboot.h - a tool to inject a bootloader into a Telechips 77X/78X firmware + * file. + * + * Copyright (C) 2009 Tomer Shalev + * + * 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 _MKTCCBOOT_H_ +#define _MKTCCBOOT_H_ + +/* win32 compatibility */ +#ifndef O_BINARY +#define O_BINARY 0 + +#endif +#ifdef __cplusplus +extern "C" { +#endif + +/* Injects a bootloader into a Telechips 77X/78X firmware file */ +unsigned char *patch_firmware_tcc(unsigned char *of_buf, int of_size, + unsigned char *boot_buf, int boot_size, int *patched_size); + +unsigned char *file_read(char *filename, int *size); + +/* Test TCC firmware file for consistency using CRC test */ +int test_firmware_tcc(unsigned char* buf, int length); + +#ifdef __cplusplus +}; +#endif + +#endif -- cgit v1.2.3