Initial version of a BSD-licensed beastpatcher utility for Gigabeat S installation. Currently only compiles on Linux, but Windows and OS X support are planned.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20083 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dave Chapman 2009-02-22 13:54:46 +00:00
parent 65d404ff6a
commit c06071e2e7
6 changed files with 596 additions and 0 deletions

View File

@ -0,0 +1,52 @@
CFLAGS=-Wall -W
ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
OUTPUT=beastpatcher.exe
CROSS=
else
OUTPUT=beastpatcher
CROSS=i586-mingw32msvc-
endif
ifeq ($(OUTPUT),beastpatcher)
LIBS = /usr/lib/libmtp.a /usr/lib/libusb.a
CFLAGS += $(shell printf \
'\#include <libmtp.h>\nlibmtp version: LIBMTP_VERSION\n' | \
gcc -E -P - -o - | grep -q '^libmtp version: 0\.2' && echo '-DOLDMTP')
else
CFLAGS+=-mno-cygwin
LIBS = ../MTP_DLL.dll
endif
NATIVECC = gcc
CC = $(CROSS)gcc
all: $(OUTPUT)
beastpatcher: beastpatcher.c bootimg.c mtp_common.h mtp_libmtp.c
gcc $(CFLAGS) -o beastpatcher beastpatcher.c bootimg.c mtp_libmtp.c $(LIBS)
strip beastpatcher
beastpatcher.exe: beastpatcher.c bootimg.c mtp_common.h mtp_win32.c $(LIBS)
$(CROSS)$(CC) $(CFLAGS) $(LIBS) -o beastpatcher.exe beastpatcher.c bootimg.c
$(CROSS)strip beastpatcher.exe
beastpatcher-mac: beastpatcher-i386 beastpatcher-ppc
lipo -create beastpatcher-ppc beastpatcher-i386 -output beastpatcher-mac
beastpatcher-i386: beastpatcher.c bootimg.c usb.h libusb-i386.a
$(CC) -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -framework iokit -framework coreservices -arch i386 $(CFLAGS) -o beastpatcher-i386 beastpatcher.c bootimg.c -I. libusb-i386.a
strip beastpatcher-i386
beastpatcher-ppc: beastpatcher.c bootimg.c usb.h libusb-ppc.a
$(CC) -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -framework iokit -framework coreservices -arch ppc $(CFLAGS) -o beastpatcher-ppc beastpatcher.c bootimg.c -I. libusb-ppc.a
strip beastpatcher-ppc
bin2c: ../../../rbutil/sansapatcher/bin2c.c
$(NATIVECC) $(CFLAGS) -o bin2c ../../../rbutil/sansapatcher/bin2c.c
bootimg.c: bootloader.bin bin2c
./bin2c bootloader.bin bootimg
clean:
rm -f beastpatcher.exe beastpatcher-mac beastpatcher-i386 beastpatcher-ppc beastpatcher bin2c bootimg.c bootimg.h *~

View File

@ -0,0 +1,61 @@
beastpatcher - a tool for installing the Rockbox bootloader on the Gigabeat S
Unlike most other parts of the Rockbox project, this tool is
distributed under the BSD license. This is due to the fact that the
Windows version links with the Microsoft MTP library.
Building instructions - All OSes
--------------------------------
For all versions, you need to copy a "bootloader.bin" file (containing
the Rockbox bootloader) into this directory.
This can be built from the Rockbox source by selecting "41" and then
"B" when running tools/configure.
You need the Rockbox toolchain to build any Rockbox target binaries -
this can be downloaded and built with the tools/rockboxdev.sh script.
The latest officially released bootloader can always be downloaded from:
http://download.rockbox.org/bootloader/gigabeat-s/
Linux
-----
The Unix versions requires libmtp, which in turn requires libusb.
beastpatcher is built to statically link to these libraries and
expects them to exist as /usr/lib/libmtp.a and /usr/lib/libusb.a
respectively. Change the definition of LIBS in the Makefile if this
is not the case for your system.
After this, just type "make" to get a
OS X
----
[Not yet implemented]
The OS X build is a universal binary statically linked with libusb and libmtp.
Windows
-------
[Not yet implemented]
The MTP_DLL.dll requires VC2005 to compile - see instructions in
MTP_DLL/README
To compile beastpatcher itself, you can either cross-compile from
Linux using the mingw32 package, or compile in Cygwin. Just type
"make beastpatcher.exe" (in Linux) or "make" (in Cygwin).

View File

@ -0,0 +1,17 @@
Basic implementation:
* Windows support - need to expand API provided by MTP_DLL.dll
* OS X support - need to statically link against libusb and libmtp
* Load bootloader.bin from a file
Ideas for future features:
* Dual-boot. Look for nk.bin in current directory, and check its
md5sum to confirm it's an original firmware. Possibly include
override for user-modified OFs, and option for user to specify an
alternate location.
This will give the user three options - rockbox only, OF only
(i.e. uninstall) or dual-boot. It would be easy to give the choice
of two boot orders (RB on hold or OF on hold) if that was desired.

View File

@ -0,0 +1,221 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* $Id:$
*
* Copyright (c) 2009, Dave Chapman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "mtp_common.h"
#include "bootimg.h"
#define VERSION "1.0 with v1 bootloader"
void print_usage(void)
{
fprintf(stderr,"Usage: beastpatcher [action]\n");
fprintf(stderr,"\n");
fprintf(stderr,"Where [action] is one of the following options:\n");
fprintf(stderr," --install (default)\n");
fprintf(stderr," -?, --help\n");
fprintf(stderr,"\n");
}
/* Code to create a single-boot bootloader.
Based on tools/gigabeats.c by Will Robertson.
*/
/* Entry point (and load address) for the main Rockbox bootloader */
#define BL_ENTRY_POINT 0x8a000000
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 calc_csum(const unsigned char* pb, int cb)
{
uint32_t l = 0;
while (cb--)
l += *pb++;
return l;
}
static void create_single_boot(unsigned char* boot, int bootlen,
unsigned char** fwbuf, int* fwsize)
{
unsigned char* buf;
/* 15 bytes for header, 16 for signature bypass,
* 12 for record header, size of bootloader, 12 for footer */
*fwsize = 15 + 16 + 12 + bootlen + 12;
*fwbuf = malloc(*fwsize);
if(buf == NULL) {
fprintf(stderr, "[ERR] Cannot allocate memory.\n" );
*fwbuf = NULL;
*fwsize = 0;
return;
}
buf = *fwbuf;
/* Copy bootloader image. */
memcpy(buf + 43, boot, bootlen);
/* Step 2: Create the file header */
sprintf((char *)buf, "B000FF\n");
put_uint32le(0x88200000, buf+7);
/* If the value below is too small, the update will attempt to flash.
* Be careful when changing this (leaving it as is won't cause issues) */
put_uint32le(0xCC0CD8, buf+11);
/* Step 3: Add the signature bypass record */
put_uint32le(0x88065A10, buf+15);
put_uint32le(4, buf+19);
put_uint32le(0xE3A00001, buf+27);
put_uint32le(calc_csum(buf+27,4), buf+23);
/* Step 4: Create a record for the actual code */
put_uint32le(BL_ENTRY_POINT, buf+31);
put_uint32le(bootlen, buf+35);
put_uint32le(calc_csum(buf + 43, bootlen), buf+39);
/* Step 5: Write the footer */
put_uint32le(0, buf+*fwsize-12);
put_uint32le(BL_ENTRY_POINT, buf+*fwsize-8);
put_uint32le(0, buf+*fwsize-4);
return;
}
int beastpatcher(int argc, char* argv[])
{
char yesno[4];
unsigned char* fwbuf;
int fwsize;
struct mtp_info_t mtp_info;
(void)argv;
fprintf(stderr,"beastpatcher v" VERSION " - (C) 2009 by the Rockbox developers\n");
fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
/* No options are currently implemented, so just display help if any are
provided. */
if (argc > 1) {
print_usage();
return 1;
}
if (mtp_init(&mtp_info) < 0) {
fprintf(stderr,"[ERR] Can not init MTP\n");
return 1;
}
/* Scan for attached MTP devices. */
if (mtp_scan(&mtp_info) < 0)
{
fprintf(stderr,"[ERR] No devices found\n");
return 1;
}
printf("[INFO] Found device \"%s - %s\"\n", mtp_info.manufacturer,
mtp_info.modelname);
printf("[INFO] Device version: \"%s\"\n",mtp_info.version);
printf("\nEnter i to install the Rockbox bootloader or c to cancel and do nothing (i/c): ");
if (fgets(yesno,4,stdin))
{
if (yesno[0]=='i')
{
/* Create a single-boot bootloader from the embedded bootloader */
create_single_boot(bootimg, LEN_bootimg, &fwbuf, &fwsize);
if (fwbuf == NULL)
return 1;
if (mtp_send_firmware(&mtp_info, fwbuf, fwsize) == 0)
{
fprintf(stderr,"[INFO] Bootloader installed successfully.\n");
}
else
{
fprintf(stderr,"[ERR] Bootloader install failed.\n");
}
/* We are now done with the firmware image */
free(fwbuf);
}
else
{
fprintf(stderr,"[INFO] Installation cancelled.\n");
}
}
mtp_finished(&mtp_info);
return 0;
}
int main(int argc, char* argv[])
{
int res;
char yesno[4];
res = beastpatcher(argc, argv);
printf("\nPress ENTER to exit beastpatcher: ");
fgets(yesno,4,stdin);
return res;
}

View File

@ -0,0 +1,71 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* $Id:$
*
* Copyright (c) 2009, Dave Chapman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef _MTP_COMMON_H
#define _MTP_COMMON_H
#ifdef __WIN32__
#error Windows support not yet implemented
#else
#include "libmtp.h"
#endif
struct mtp_info_t
{
/* Generic data */
char manufacturer[200];
char modelname[200];
char version[200];
/* OS-Specific data */
#ifdef __WIN32__
#else
LIBMTP_mtpdevice_t *device;
#endif
};
/* Common functions for both libMTP and win32 */
int mtp_init(struct mtp_info_t* mtp_info);
int mtp_finished(struct mtp_info_t* mtp_info);
int mtp_scan(struct mtp_info_t* mtp_info);
int mtp_send_firmware(struct mtp_info_t* mtp_info, unsigned char* fwbuf,
int fwsize);
#endif /* !_MTP_COMMON_H */

View File

@ -0,0 +1,174 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* $Id:$
*
* Copyright (c) 2009, Dave Chapman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
****************************************************************************/
#include <string.h>
#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <inttypes.h>
#include "libmtp.h"
#include "mtp_common.h"
int mtp_init(struct mtp_info_t* mtp_info)
{
/* Fill the info struct with zeros - mainly for the strings */
memset(mtp_info, 0, sizeof(struct mtp_info_t));
LIBMTP_Init();
return 0;
}
int mtp_finished(struct mtp_info_t* mtp_info)
{
LIBMTP_Release_Device(mtp_info->device);
return 0;
}
int mtp_scan(struct mtp_info_t* mtp_info)
{
char* str;
mtp_info->device = LIBMTP_Get_First_Device();
if (mtp_info->device == NULL)
{
return -1;
}
else
{
/* NOTE: These strings are filled with zeros in mtp_init() */
if ((str = LIBMTP_Get_Manufacturername(mtp_info->device)))
{
strncpy(mtp_info->manufacturer, str, sizeof(mtp_info->manufacturer)-1);
}
if ((str = LIBMTP_Get_Modelname(mtp_info->device)))
{
strncpy(mtp_info->modelname, str, sizeof(mtp_info->modelname)-1);
}
if ((str = LIBMTP_Get_Deviceversion(mtp_info->device)))
{
strncpy(mtp_info->version, str, sizeof(mtp_info->version)-1);
}
return 0;
}
}
static int progress(uint64_t const sent, uint64_t const total,
void const *const data)
{
(void)data;
int percent = (sent * 100) / total;
#ifdef __WIN32__
printf("Progress: %I64u of %I64u (%d%%)\r", sent, total, percent);
#else
printf("Progress: %"PRIu64" of %"PRIu64" (%d%%)\r", sent, total, percent);
#endif
fflush(stdout);
return 0;
}
int mtp_send_firmware(struct mtp_info_t* mtp_info, unsigned char* fwbuf,
int fwsize)
{
LIBMTP_file_t *genfile;
int ret;
size_t n;
FILE* fwfile;
/* Open a temporary file - this will be automatically deleted when closed */
fwfile = tmpfile();
if (fwfile == NULL)
{
fprintf(stderr,"[ERR] Could not create temporary file.\n");
return -1;
}
n = fwrite(fwbuf, 1, fwsize, fwfile);
if ((int)n < fwsize)
{
fprintf(stderr,"[ERR] Could not write to temporary file - n = %d.\n",(int)n);
fclose(fwfile);
return -1;
}
/* Reset file pointer */
fseek(fwfile, SEEK_SET, 0);
/* Prepare for uploading firmware */
genfile = LIBMTP_new_file_t();
genfile->filetype = LIBMTP_FILETYPE_FIRMWARE;
genfile->filename = strdup("nk.bin");
genfile->filesize = fwsize;
#ifdef OLDMTP
ret = LIBMTP_Send_File_From_File_Descriptor(mtp_info->device,
fileno(fwfile), genfile, progress, NULL, 0);
#else
ret = LIBMTP_Send_File_From_File_Descriptor(mtp_info->device,
fileno(fwfile), genfile, progress, NULL);
#endif
/* Keep the progress line onscreen */
printf("\n");
/* NOTE: According to the docs, a value of ret != 0 means error, but libMTP
seems to return that even when successful. So we can't check the return
code.
*/
/* Cleanup */
LIBMTP_destroy_file_t(genfile);
/* Close the temporary file - this also deletes it. */
fclose(fwfile);
return 0;
}