summaryrefslogtreecommitdiffstats
path: root/rbutil
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2009-05-28 18:27:08 +0000
committerRafaël Carré <rafael.carre@gmail.com>2009-05-28 18:27:08 +0000
commit96165abec2da60c466659fa0e68e06d97587d51a (patch)
tree5445bddea2ac0e706546ce972d61dacc8d0f81e2 /rbutil
parentbebc8587cfa7896684278d824ed5b28b2e9f9df1 (diff)
downloadrockbox-96165abec2da60c466659fa0e68e06d97587d51a.tar.gz
rockbox-96165abec2da60c466659fa0e68e06d97587d51a.tar.bz2
rockbox-96165abec2da60c466659fa0e68e06d97587d51a.zip
FS#10253 : mkamsboot v1.0mkamsboot_1.0
- Bump version to 1.0 - Add Clipv2 target - Make mkamsboot work as a library (work by domonoky : FS#10185, with a few modifications by me) . Use a macro with variadic arguments for error cases in functions which might error. . Add detailed descriptions to functions exported by the library (in the header file) - modify bin2c.c to produce only one pair of .c/.h files with several files embedded in it - move files needing to be built by an ARM cross compiler into dualboot/ - commit produced .c/.h files (containing nrv2e_d8.S and dualboot.S built for Clip, Fuze, e200v2, c200v2, m200v4, Clipv2) - Write a real README file - cosmetics: indent dualboot.S properly, remove trailing spaces, limit lines to 80 characters - comments: add/correct comments in dualboot.S and mkamsboot.c - move back extract_fw.c to utils/AMS/hacking git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21118 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil')
-rw-r--r--rbutil/mkamsboot/Makefile106
-rw-r--r--rbutil/mkamsboot/README61
-rw-r--r--rbutil/mkamsboot/bin2c.c134
-rw-r--r--rbutil/mkamsboot/dualboot.S184
-rw-r--r--rbutil/mkamsboot/dualboot.c118
-rw-r--r--rbutil/mkamsboot/dualboot.h9
-rw-r--r--rbutil/mkamsboot/dualboot/Makefile54
-rw-r--r--rbutil/mkamsboot/dualboot/bin2c.c131
-rw-r--r--rbutil/mkamsboot/dualboot/dualboot.S220
-rw-r--r--rbutil/mkamsboot/dualboot/nrv2e_d8.S (renamed from rbutil/mkamsboot/nrv2e_d8.S)1
-rw-r--r--rbutil/mkamsboot/extract_fw.c129
-rw-r--r--rbutil/mkamsboot/md5.c2
-rw-r--r--rbutil/mkamsboot/mkamsboot.c598
-rw-r--r--rbutil/mkamsboot/mkamsboot.h124
14 files changed, 1054 insertions, 817 deletions
diff --git a/rbutil/mkamsboot/Makefile b/rbutil/mkamsboot/Makefile
index 5a62650904..1a5ffd09f3 100644
--- a/rbutil/mkamsboot/Makefile
+++ b/rbutil/mkamsboot/Makefile
@@ -1,90 +1,48 @@
-CC=gcc
-
# We use the UCL code available in the Rockbox tools/ directory
-CFLAGS=-I../../tools/ucl/include
+CFLAGS=-I../../tools/ucl/include -Wall
LIBUCL=../../tools/ucl/src/libucl.a
-# Edit the following variables (plus copy/paste another set of rules) when
-# adding a new target. mkamsboot.c also needs to be edited to refer to these
-# new images.
-
-BOOTIMAGES = dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o
-BOOTHEADERS = dualboot_clip.h dualboot_e200v2.h dualboot_c200v2.h dualboot_m200v4.h dualboot_fuze.h
-
-CLIPFILES = dualboot_clip.arm-o dualboot_clip.o dualboot_clip.c dualboot_clip.h
-
-E200V2FILES = dualboot_e200v2.arm-o dualboot_e200v2.o dualboot_e200v2.c \
- dualboot_e200v2.h
-
-M200V4FILES = dualboot_m200v4.arm-o dualboot_m200v4.o dualboot_m200v4.arm-bin \
- dualboot_m200v4.c dualboot_m200v4.h
-
-C200V2FILES = dualboot_c200v2.arm-o dualboot_c200v2.o dualboot_c200v2.c \
- dualboot_c200v2.h
-
-FUZEFILES = dualboot_fuze.arm-o dualboot_fuze.o dualboot_fuze.c dualboot_fuze.h
-
-all: mkamsboot
-
-# Dualboot bootloaders
-
-dualboot_clip.arm-o: dualboot.S
- arm-elf-gcc -DSANSA_CLIP -c -o dualboot_clip.arm-o dualboot.S
-
-dualboot_fuze.arm-o: dualboot.S
- arm-elf-gcc -DSANSA_FUZE -c -o dualboot_fuze.arm-o dualboot.S
-
-dualboot_e200v2.arm-o: dualboot.S
- arm-elf-gcc -DSANSA_E200V2 -c -o dualboot_e200v2.arm-o dualboot.S
-
-dualboot_m200v4.arm-o: dualboot.S
- arm-elf-gcc -DSANSA_M200V4 -c -o dualboot_m200v4.arm-o dualboot.S
-
-dualboot_c200v2.arm-o: dualboot.S
- arm-elf-gcc -DSANSA_C200V2 -c -o dualboot_c200v2.arm-o dualboot.S
-
-# Rules for the ucl unpack function
-nrv2e_d8.arm-o: nrv2e_d8.S
- arm-elf-gcc -DPURE_THUMB -c -o nrv2e_d8.arm-o nrv2e_d8.S
-
-
+ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
+OUTPUT=mkamsboot.exe
+CFLAGS+=-mno-cygwin
+else
+ifeq ($(findstring MINGW,$(shell uname)),MINGW)
+OUTPUT=mkamsboot.exe
+else
+ifeq ($(findstring mingw,$(CC)),mingw)
+OUTPUT=mkamsboot.exe
+else
+OUTPUT=mkamsboot
+endif
+endif
+endif
+
+CC?= gcc
+
+all: $(OUTPUT)
$(LIBUCL):
make -C ../../tools/ucl/src libucl.a
+# This file can be generated in the dualboot/ directory
+dualboot.o: dualboot.c
+ $(CC) $(CFLAGS) -c -o dualboot.o dualboot.c
+
md5.o: md5.c md5.h
$(CC) $(CFLAGS) -c -o md5.o -W -Wall md5.c
-mkamsboot.o: mkamsboot.c $(BOOTHEADERS) nrv2e_d8.h md5.h
+mkamsboot.o: mkamsboot.c dualboot.h md5.h
$(CC) $(CFLAGS) -c -o mkamsboot.o -W -Wall mkamsboot.c
-mkamsboot: mkamsboot.o $(BOOTIMAGES) nrv2e_d8.o md5.o $(LIBUCL)
- $(CC) -o mkamsboot mkamsboot.o $(BOOTIMAGES) nrv2e_d8.o md5.o $(LIBUCL)
-
-# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
-# the binary code and finally convert to .c/.h for linking with mkamsboot
-
-%.arm-elf: %.arm-o
- arm-elf-ld -e 0 -Ttext=0 -o $@ $<
-
-%.arm-bin: %.arm-elf
- arm-elf-objcopy -O binary $< $@
-
-%.c %.h: %.arm-bin bin2c
- ./bin2c $< $*
-
-# Generic host rule.
-%.o: %.c
- $(CC) $(CFLAGS) -c -o $@ $<
+$(OUTPUT): mkamsboot.o md5.o dualboot.o $(LIBUCL)
+ $(CC) $(CFLAGS) -o $(OUTPUT) mkamsboot.o md5.o dualboot.o $(LIBUCL)
-# Cancel the implicit .S -> .o rule
-%.o: %.S
+libmkamsboot.o: mkamsboot.c dualboot.h md5.h
+ $(CC) $(CFLAGS) -DLIB -c -o libmkamsboot.o -W -Wall mkamsboot.c
-bin2c: bin2c.c
- $(CC) -o bin2c bin2c.c
+libmkamsboot.a: libmkamsboot.o md5.o dualboot.o
+ $(AR) ruv libmkamsboot.a libmkamsboot.o md5.o dualboot.o
clean:
- rm -f mkamsboot mkamsboot.o nrv2e_d8.arm-o nrv2e_d8.arm-elf \
- nrv2e_d8.arm-bin *~ bin2c nrv2e_d8.c nrv2e_d8.h nrv2e_d8.o md5.o \
- $(BOOTIMAGES) $(CLIPFILES) $(E200V2FILES) $(M200V4FILES) $(FUZEFILES) \
- $(C200V2FILES)
+ rm -f $(OUTPUT) mkamsboot.o *~ md5.o dualboot.o \
+ libmkamsboot.o libmkamsboot.a
diff --git a/rbutil/mkamsboot/README b/rbutil/mkamsboot/README
index bd0d2a3eea..53f1fba9b9 100644
--- a/rbutil/mkamsboot/README
+++ b/rbutil/mkamsboot/README
@@ -3,4 +3,63 @@ mkamsboot
A tool to inject a bootloader into a Sansa V2 (AMS) firmware file.
-See comments in mkamsboot.c and dualboot.S for more information.
+
+Usage
+-----
+
+mkamsboot <firmware file> <boot file> <output file>
+
+<firmware file> is an original Sansa firmware file obtained from the Sansa
+ forums for example : http://forums.sandisk.com/sansa/?category.id=devices
+
+<boot file> is the code you want to execute (a rockbox bootloader), previously
+ scrambled with tools/scramble utility.
+
+<output file> is the resulting firmware file which you'll have to copy on your
+ Sansa player. See "Firmware filenames".
+
+
+Supported models
+----------------
+
+Sansa Clip : firmware version starting with "01."
+Sansa Clipv2: firmware version starting with "02."
+Sansa Fuze : firmware version starting with "01."
+Sansa E200v2: firmware version starting with "03."
+Sansa C200v2: firmware version starting with "03."
+Sansa M200v4: firmware version starting with "4."
+
+
+Firmware filenames
+------------------
+
+For the firmware upgrade to happen, the firmware has to be named specially:
+
+clip v2 : m30pa.bin
+clip : m300a.bin
+fuze : fuzea.bin
+e200v2 : e200pa.bin
+c200v2 : c200pa.bin
+m200v4 : m200a.bin
+
+
+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 Left key.
+ ***Note : on the c200v2 you need to press the Right key.
+
+ The player will boot into the Original Firmware as well if it is powered up by
+inserting an usb cable.
+ ***Note : on the m200v4 powering up by usb will cause booting into the new
+firmware
+
+Hacking
+-------
+
+See comments in mkamsboot.c and dualboot/dualboot.S for more information.
diff --git a/rbutil/mkamsboot/bin2c.c b/rbutil/mkamsboot/bin2c.c
deleted file mode 100644
index dce8013c31..0000000000
--- a/rbutil/mkamsboot/bin2c.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2007 Dave Chapman
- *
- * 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 <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdlib.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-static off_t filesize(int fd)
-{
- struct stat buf;
-
- fstat(fd,&buf);
- return buf.st_size;
-}
-
-static int write_cfile(const unsigned char* buf, off_t len, const char* cname)
-{
- char filename[256];
- FILE* fp;
- int i;
-
- snprintf(filename,256,"%s.c",cname);
-
- fp = fopen(filename,"w+");
- if (fp == NULL) {
- fprintf(stderr,"Couldn't open %s\n",filename);
- return -1;
- }
-
- fprintf(fp,"/* Generated by bin2c */\n\n");
- fprintf(fp,"unsigned char %s[%d] = {",cname,len);
-
- for (i=0;i<len;i++) {
- if ((i % 16) == 0) {
- fprintf(fp,"\n ");
- }
- if (i == (len-1)) {
- fprintf(fp,"0x%02x",buf[i]);
- } else {
- fprintf(fp,"0x%02x, ",buf[i]);
- }
- }
- fprintf(fp,"\n};\n");
-
- fclose(fp);
- return 0;
-}
-
-static int write_hfile(off_t len, const char* cname)
-{
- char filename[256];
- FILE* fp;
-
- snprintf(filename,256,"%s.h",cname);
- fp = fopen(filename,"w+");
- if (fp == NULL) {
- fprintf(stderr,"Couldn't open %s\n",filename);
- return -1;
- }
-
- fprintf(fp,"/* Generated by bin2c */\n\n");
- fprintf(fp,"extern unsigned char %s[%d];\n",cname,len);
- fclose(fp);
- return 0;
-}
-
-int main (int argc, char* argv[])
-{
- char* infile;
- char* cname;
- int fd;
- unsigned char* buf;
- int len;
- int n;
-
- if (argc != 3) {
- fprintf(stderr,"Usage: bin2c file cname\n");
- return 0;
- }
-
- infile=argv[1];
- cname=argv[2];
-
- fd = open(infile,O_RDONLY|O_BINARY);
- if (fd < 0) {
- fprintf(stderr,"Can not open %s\n",infile);
- return 0;
- }
-
- len = filesize(fd);
-
- buf = malloc(len);
- n = read(fd,buf,len);
- if (n < len) {
- fprintf(stderr,"Short read, aborting\n");
- return 0;
- }
- close(fd);
-
- if (write_cfile(buf,len,cname) < 0) {
- return -1;
- }
- if (write_hfile(len,cname) < 0) {
- return -1;
- }
-
- return 0;
-}
diff --git a/rbutil/mkamsboot/dualboot.S b/rbutil/mkamsboot/dualboot.S
deleted file mode 100644
index a4d0469060..0000000000
--- a/rbutil/mkamsboot/dualboot.S
+++ /dev/null
@@ -1,184 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2008 Rafaël Carré
- *
- * 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.
- *
- ****************************************************************************/
-
-.text
-
-.set IRAM_SIZE, 0x50000
-
-.set GPIOA, 0xC80B0000
-.set GPIOB, 0xC80C0000
-.set GPIOC, 0xC80D0000
-.set GPIOD, 0xC80E0000
-.set CGU_PERI, 0xC80F0014
-
-
-/* Vectors */
- ldr pc, =start
-.word 0
-.word 0
-.word 0
-.word 0
-.word 0
-.word 0
-.word 0
-
-/* These values are filled in by mkamsboot - don't move them from offset 0x20 */
-uclunpack_end: .word 0 /* End of the ucl_unpack function */
-uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */
-
-ucl_of_end: .word 0 /* End of the ucl-compressed OF image */
-ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */
-
-ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */
-ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */
-
-
-start:
- /* First copy the UCL unpack function to the end of RAM */
- ldr r0, uclunpack_end /* Source */
- ldr r1, uclunpack_size /* Source length */
- sub r2, r0, r1 /* Source start - 1*/
-
- ldr r3, =(IRAM_SIZE-1) /* Destination end */
-
-uclcopy:
- ldrb r4, [r0], #-1
- strb r4, [r3], #-1
- cmp r2, r0
- bne uclcopy
-
- add r5, r3, #2 /* r5 is entry point of copy of uclunpack */
- /* function, plus one (for thumb mode */
-
- /* enable gpio clock */
- ldr r0, =CGU_PERI
- ldr r1, [r0]
- orr r1, r1, #(1<<16)
- str r1, [r0]
-
-
-#ifndef SANSA_M200V4 /* this doesnt work for m200 */
- /* we check A3 unconditionally of the model because it seems to be */
- /* either hold, either usb on every model */
- /* TODO: make it USB on all AMS Sansas for consistency, USB is safer too */
-
- ldr r0, =GPIOA
- mov r1, #0
- str r1, [r0, #0x400]
-#ifdef SANSA_C200V2
- ldr r1, [r0, #0x8] /* USB is A1 on C200 */
-#elif defined(SANSA_CLIP)
- ldr r1, [r0, #0x100] /* USB is A6 on Clip */
-#else
- ldr r1, [r0, #0x20] /* read pin A3 */
-#endif
- cmp r1, #0
- bne boot_of
-#endif
-
- /* here are model specific tests, for dual boot without a computer */
-
-#ifdef SANSA_CLIP
- /* LEFT button */
-.set row, (1<<5) /* enable output on C5 */
- ldr r0, =GPIOC
- mov r1, #row
- str r1, [r0, #0x400]
- str r1, [r0, #(4*row)]
-
-.set col, (1<<0) /* read keyscan column B0 */
- ldr r0, =GPIOB
- mov r1, #0
- str r1, [r0, #0x400]
- ldr r1, [r0, #(4*col)]
-
- cmp r1, #0
- bne boot_of
-#elif defined(SANSA_E200V2) || defined(SANSA_FUZE)
- /* LEFT button */
- ldr r0, =GPIOC
- mov r1, #0
- str r1, [r0, #0x400]
- ldr r1, [r0, #0x20] /* read pin C3 */
-
- cmp r1, #0 /* C3 = #0 means button pressed */
- beq boot_of
-#elif defined(SANSA_C200V2)
- /* check for RIGHT on C6, should maybe changed to LEFT as soon as it
- * known in which pin that is in order for consistency */
- ldr r0, =GPIOC
- mov r1, #0
- str r1, [r0, #0x400] /* set pin to output */
-
- ldr r1, [r0, #256] /* 1<<(6+2) */
- cmp r1, #0 /* C6 low means button pressed */
- beq boot_of
-#elif defined(SANSA_M200V4)
- /* LEFT button */
-.set row, (1<<5) /* enable output on A5 */
- ldr r0, =GPIOA
- mov r1, #row
- str r1, [r0, #0x400]
- str r1, [r0, #(4*row)]
-
-.set col, (1<<0) /* read keyscan column A0 */
- ldr r2, [r0, #(4*col)]
-
- /* check value read (1 means button pressed) */
- cmp r2, #0
- bne boot_of
-#else
- #error No target-specific key check defined!
-#endif
-
- /* No button was held, so we boot rockbox */
- ldr r0, ucl_rb_end /* Address of compressed image */
- ldr r1, ucl_rb_size /* Compressed size */
- b decompress
-
-boot_of:
- ldr r0, ucl_of_end /* Address of compressed image */
- ldr r1, ucl_of_size /* Compressed size */
-
-
-decompress:
- /* At this point: */
- /* r5 = entry point (plus one for thumb) of uclunpack function */
- /* r3 = destination_end for copy of UCL image */
- /* r0 = source_end for UCL image to copy */
- /* r1 = size of UCL image to copy */
-
- sub r4, r3, r1 /* r4 := destination_start - 1 */
-
-fw_copy:
- ldrb r2, [r0], #-1
- strb r2, [r3], #-1
- cmp r3, r4 /* Stop when we reached dest_start-1 */
- bne fw_copy
-
- /* Call the ucl decompress function, which will branch to 0x0 */
- /* on completion */
- add r0, r3, #1 /* r0 := Start of compressed image */
- /* r1 already contains compressed size */
- mov r2, #0 /* r2 := Destination for unpacking */
- bx r5 /* Branch to uclunpack, switching to thumb */
-
- /* never reached */
diff --git a/rbutil/mkamsboot/dualboot.c b/rbutil/mkamsboot/dualboot.c
new file mode 100644
index 0000000000..2eda3930cd
--- /dev/null
+++ b/rbutil/mkamsboot/dualboot.c
@@ -0,0 +1,118 @@
+/* Generated by bin2c */
+
+unsigned char nrv2e_d8[168] = {
+ 0x0f, 0x18, 0x01, 0x24, 0x65, 0x42, 0xe4, 0x07, 0x05, 0x26, 0x36, 0x02, 0x0a, 0xe0, 0x00, 0x20,
+ 0x00, 0x47, 0x04, 0x78, 0x64, 0x41, 0x01, 0x30, 0x24, 0x06, 0xf7, 0x46, 0x03, 0x78, 0x01, 0x30,
+ 0x13, 0x70, 0x01, 0x32, 0x24, 0x19, 0xfe, 0x46, 0xf3, 0xd0, 0xf7, 0xd2, 0x01, 0x21, 0x04, 0xe0,
+ 0x01, 0x39, 0x24, 0x19, 0xfe, 0x46, 0xec, 0xd0, 0x49, 0x41, 0x24, 0x19, 0xfe, 0x46, 0xe8, 0xd0,
+ 0x49, 0x41, 0x24, 0x19, 0xfe, 0x46, 0xe4, 0xd0, 0xf2, 0xd3, 0xcb, 0x1e, 0x00, 0x21, 0x08, 0xd3,
+ 0x1b, 0x02, 0x05, 0x78, 0x01, 0x30, 0x1d, 0x43, 0xed, 0x43, 0xd8, 0xd0, 0x6d, 0x10, 0x13, 0xd2,
+ 0x03, 0xe0, 0x24, 0x19, 0xfe, 0x46, 0xd4, 0xd0, 0x0e, 0xd2, 0x01, 0x21, 0x24, 0x19, 0xfe, 0x46,
+ 0xcf, 0xd0, 0x09, 0xd2, 0x24, 0x19, 0xfe, 0x46, 0xcb, 0xd0, 0x49, 0x41, 0x24, 0x19, 0xfe, 0x46,
+ 0xc7, 0xd0, 0xf7, 0xd3, 0x04, 0x31, 0x04, 0xe0, 0x24, 0x19, 0xfe, 0x46, 0xc1, 0xd0, 0x49, 0x41,
+ 0x02, 0x31, 0xee, 0x42, 0x00, 0xd2, 0x01, 0x31, 0x13, 0x78, 0x53, 0x5d, 0x13, 0x70, 0x01, 0x32,
+ 0x01, 0x39, 0xfa, 0xd1, 0xbe, 0xe7, 0x00, 0x00
+};
+unsigned char dualboot_clip[248] = {
+ 0xd8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
+ 0x01, 0x20, 0x40, 0xe0, 0x98, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
+ 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x84, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x78, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x00, 0x11, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
+ 0x0c, 0x00, 0x00, 0x1a, 0x64, 0x00, 0x9f, 0xe5, 0x20, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
+ 0x80, 0x10, 0x80, 0xe5, 0x58, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
+ 0x04, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x1a, 0x84, 0x00, 0x1f, 0xe5,
+ 0x84, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x98, 0x00, 0x1f, 0xe5, 0x98, 0x10, 0x1f, 0xe5,
+ 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
+ 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
+ 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
+ 0x00, 0x00, 0x0d, 0xc8, 0x00, 0x00, 0x0c, 0xc8
+};
+unsigned char dualboot_e200v2[228] = {
+ 0xc8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
+ 0x01, 0x20, 0x40, 0xe0, 0x88, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
+ 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x74, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x68, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
+ 0x08, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
+ 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x74, 0x00, 0x1f, 0xe5,
+ 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x88, 0x00, 0x1f, 0xe5, 0x88, 0x10, 0x1f, 0xe5,
+ 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
+ 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
+ 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
+ 0x00, 0x00, 0x0d, 0xc8
+};
+unsigned char dualboot_c200v2[228] = {
+ 0xc8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
+ 0x01, 0x20, 0x40, 0xe0, 0x88, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
+ 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x74, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x68, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x08, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
+ 0x08, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
+ 0x00, 0x11, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x74, 0x00, 0x1f, 0xe5,
+ 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x88, 0x00, 0x1f, 0xe5, 0x88, 0x10, 0x1f, 0xe5,
+ 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
+ 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
+ 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
+ 0x00, 0x00, 0x0d, 0xc8
+};
+unsigned char dualboot_m200v4[204] = {
+ 0xb4, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
+ 0x01, 0x20, 0x40, 0xe0, 0x74, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
+ 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x60, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x54, 0x00, 0x9f, 0xe5,
+ 0x20, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x80, 0x10, 0x80, 0xe5, 0x04, 0x20, 0x90, 0xe5,
+ 0x00, 0x00, 0x52, 0xe3, 0x02, 0x00, 0x00, 0x1a, 0x60, 0x00, 0x1f, 0xe5, 0x60, 0x10, 0x1f, 0xe5,
+ 0x01, 0x00, 0x00, 0xea, 0x74, 0x00, 0x1f, 0xe5, 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x40, 0x43, 0xe0,
+ 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1, 0xfb, 0xff, 0xff, 0x1a,
+ 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1, 0x38, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8
+};
+unsigned char dualboot_fuze[228] = {
+ 0xc8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
+ 0x01, 0x20, 0x40, 0xe0, 0x88, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
+ 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x74, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x68, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
+ 0x08, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
+ 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x74, 0x00, 0x1f, 0xe5,
+ 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x88, 0x00, 0x1f, 0xe5, 0x88, 0x10, 0x1f, 0xe5,
+ 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
+ 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
+ 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
+ 0x00, 0x00, 0x0d, 0xc8
+};
+unsigned char dualboot_clipv2[272] = {
+ 0xf4, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
+ 0x01, 0x20, 0x40, 0xe0, 0xb4, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
+ 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0xa0, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x94, 0x00, 0x9f, 0xe5,
+ 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x00, 0x11, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
+ 0x13, 0x00, 0x00, 0x1a, 0x80, 0x00, 0x9f, 0xe5, 0x38, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
+ 0x08, 0x10, 0xa0, 0xe3, 0x20, 0x10, 0x80, 0xe5, 0x10, 0x10, 0xa0, 0xe3, 0x40, 0x10, 0x80, 0xe5,
+ 0x20, 0x10, 0xa0, 0xe3, 0x80, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x40, 0x10, 0x80, 0xe5,
+ 0x05, 0x10, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff, 0x1a, 0x04, 0x10, 0x90, 0xe5,
+ 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x1f, 0xe5, 0xa0, 0x10, 0x1f, 0xe5,
+ 0x01, 0x00, 0x00, 0xea, 0xb4, 0x00, 0x1f, 0xe5, 0xb4, 0x10, 0x1f, 0xe5, 0x01, 0x40, 0x43, 0xe0,
+ 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1, 0xfb, 0xff, 0xff, 0x1a,
+ 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1, 0x38, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0x0f, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8, 0x00, 0x00, 0x0e, 0xc8
+};
diff --git a/rbutil/mkamsboot/dualboot.h b/rbutil/mkamsboot/dualboot.h
new file mode 100644
index 0000000000..b88a18240f
--- /dev/null
+++ b/rbutil/mkamsboot/dualboot.h
@@ -0,0 +1,9 @@
+/* Generated by bin2c */
+
+extern unsigned char nrv2e_d8[168];
+extern unsigned char dualboot_clip[248];
+extern unsigned char dualboot_e200v2[228];
+extern unsigned char dualboot_c200v2[228];
+extern unsigned char dualboot_m200v4[204];
+extern unsigned char dualboot_fuze[228];
+extern unsigned char dualboot_clipv2[272];
diff --git a/rbutil/mkamsboot/dualboot/Makefile b/rbutil/mkamsboot/dualboot/Makefile
new file mode 100644
index 0000000000..06b90c7fb9
--- /dev/null
+++ b/rbutil/mkamsboot/dualboot/Makefile
@@ -0,0 +1,54 @@
+CC=gcc
+
+# Edit the following variables (plus copy/paste another set of rules) when
+# adding a new target. mkamsboot.c also needs to be edited to refer to these
+# new images.
+
+BOOTOBJS = nrv2e_d8.o dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o dualboot_clipv2.o
+BOOTBINS = nrv2e_d8.arm-bin dualboot_clip.arm-bin dualboot_e200v2.arm-bin dualboot_c200v2.arm-bin dualboot_m200v4.arm-bin dualboot_fuze.arm-bin dualboot_clipv2.arm-bin
+
+all: dualboot.h
+
+dualboot.h: $(BOOTBINS)
+
+# Dualboot bootloaders
+
+dualboot_clip.o: dualboot.S
+ arm-elf-gcc -DSANSA_CLIP -c -o dualboot_clip.o dualboot.S
+
+dualboot_fuze.o: dualboot.S
+ arm-elf-gcc -DSANSA_FUZE -c -o dualboot_fuze.o dualboot.S
+
+dualboot_e200v2.o: dualboot.S
+ arm-elf-gcc -DSANSA_E200V2 -c -o dualboot_e200v2.o dualboot.S
+
+dualboot_m200v4.o: dualboot.S
+ arm-elf-gcc -DSANSA_M200V4 -c -o dualboot_m200v4.o dualboot.S
+
+dualboot_c200v2.o: dualboot.S
+ arm-elf-gcc -DSANSA_C200V2 -c -o dualboot_c200v2.o dualboot.S
+
+dualboot_clipv2.o: dualboot.S
+ arm-elf-gcc -DSANSA_CLIPV2 -c -o dualboot_clipv2.o dualboot.S
+
+# Rules for the ucl unpack function
+nrv2e_d8.o: nrv2e_d8.S
+ arm-elf-gcc -DPURE_THUMB -c -o nrv2e_d8.o nrv2e_d8.S
+
+# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
+# the binary code and finally convert to .h for building in mkamsboot
+
+%.arm-elf: %.o
+ arm-elf-ld -e 0 -Ttext=0 -o $@ $<
+
+%.arm-bin: %.arm-elf
+ arm-elf-objcopy -O binary $< $@
+
+dualboot.c dualboot.h: $(BOOTBINS) bin2c
+ ./bin2c dualboot $(BOOTBINS)
+
+bin2c: bin2c.c
+ $(CC) -o bin2c bin2c.c
+
+clean:
+ rm -f *~ bin2c $(BOOTBINS) $(BOOTOBJS) dualboot.c dualboot.h
diff --git a/rbutil/mkamsboot/dualboot/bin2c.c b/rbutil/mkamsboot/dualboot/bin2c.c
new file mode 100644
index 0000000000..e8619eae87
--- /dev/null
+++ b/rbutil/mkamsboot/dualboot/bin2c.c
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 Dave Chapman
+ *
+ * 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 <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static off_t filesize(int fd)
+{
+ struct stat buf;
+
+ fstat(fd,&buf);
+ return buf.st_size;
+}
+
+static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name)
+{
+ int i;
+
+ fprintf(fp,"unsigned char %s[%ld] = {",name,len);
+
+ for (i=0;i<len;i++) {
+ if ((i % 16) == 0) {
+ fprintf(fp,"\n ");
+ }
+ if (i == (len-1)) {
+ fprintf(fp,"0x%02x",buf[i]);
+ } else if ((i % 16) == 15) {
+ fprintf(fp,"0x%02x,",buf[i]);
+ } else {
+ fprintf(fp,"0x%02x, ",buf[i]);
+ }
+ }
+ fprintf(fp,"\n};\n");
+}
+
+int main (int argc, char* argv[])
+{
+ char* cname;
+ int i;
+ FILE *cfile, *hfile;
+ char cfilename[256], hfilename[256];
+
+ if (argc < 3) {
+ fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n");
+ return 1;
+ }
+
+ cname=argv[1];
+
+ snprintf(cfilename,256,"%s.c",cname);
+ cfile = fopen(cfilename,"w+");
+ if (cfile == NULL) {
+ fprintf(stderr,"Couldn't open %s\n",cfilename);
+ return 2;
+ }
+
+ snprintf(hfilename,256,"%s.h",cname);
+ hfile = fopen(hfilename,"w+");
+ if (hfile == NULL) {
+ fprintf(stderr,"Couldn't open %s\n",hfilename);
+ fclose(cfile);
+ return 3;
+ }
+
+ fprintf(cfile,"/* Generated by bin2c */\n\n");
+ fprintf(hfile,"/* Generated by bin2c */\n\n");
+
+ for(i=0; i < argc - 2; i++) {
+ unsigned char* buf;
+ off_t len;
+ char *ext;
+ char *array = argv[2+i];
+
+ int fd = open(array,O_RDONLY|O_BINARY);
+ if (fd < 0) {
+ fprintf(stderr,"Can not open %s\n",argv[2+i]);
+ fclose(cfile);
+ fclose(hfile);
+ return 4;
+ }
+
+ len = filesize(fd);
+
+ buf = malloc(len);
+ if (read(fd,buf,len) < len) {
+ fprintf(stderr,"Short read, aborting\n");
+ return 5;
+ }
+
+ /* remove file extension */
+ ext = strchr (array, '.');
+ if (ext != NULL)
+ *ext = '\0';
+ write_cfile (buf, len, cfile, array);
+ fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len);
+
+ close(fd);
+ }
+
+ fclose(cfile);
+ fclose(hfile);
+
+ return 0;
+}
diff --git a/rbutil/mkamsboot/dualboot/dualboot.S b/rbutil/mkamsboot/dualboot/dualboot.S
new file mode 100644
index 0000000000..5210ba5160
--- /dev/null
+++ b/rbutil/mkamsboot/dualboot/dualboot.S
@@ -0,0 +1,220 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 Rafaël Carré
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+.text
+
+ #if defined(SANSA_CLIPV2)
+.set RAM_SIZE, 0x100000 /* Use 1MB of SDRAM on v2 firmwares (bigger firmware) */
+#else
+.set RAM_SIZE, 0x50000 /* Use full IRAM on v1 firmwares */
+#endif
+
+/* AS3525 hardware registers */
+.set GPIOA, 0xC80B0000
+.set GPIOB, 0xC80C0000
+.set GPIOC, 0xC80D0000
+.set GPIOD, 0xC80E0000
+.set CGU_PERI, 0xC80F0014
+
+
+/* Vectors */
+
+ ldr pc, =start /* reset vector */
+ /* next vectors are unused */
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+
+/* These values are filled in by mkamsboot - don't move them from offset 0x20 */
+
+uclunpack_end: .word 0 /* End of the ucl_unpack function */
+uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */
+
+ucl_of_end: .word 0 /* End of the ucl-compressed OF image */
+ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */
+
+ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */
+ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */
+
+
+start:
+ /* First copy the UCL unpack function to the end of RAM */
+ ldr r0, uclunpack_end /* Source */
+ ldr r1, uclunpack_size /* Source length */
+ sub r2, r0, r1 /* Source start - 1*/
+
+ ldr r3, =(RAM_SIZE-1) /* Destination end */
+
+uclcopy:
+ ldrb r4, [r0], #-1
+ strb r4, [r3], #-1
+ cmp r2, r0
+ bne uclcopy
+
+ add r5, r3, #2 /* r5 is entry point of copy of uclunpack */
+ /* function, plus one (for thumb mode */
+
+ /* enable gpio clock */
+ ldr r0, =CGU_PERI
+ ldr r1, [r0]
+ orr r1, r1, #(1<<16)
+ str r1, [r0]
+
+
+/* TODO : M200V4 */
+#if defined(SANSA_C200V2)
+#define USB_PIN 1
+#elif defined(SANSA_CLIP) || defined(SANSA_CLIPV2)
+#define USB_PIN 6
+#elif defined(SANSA_FUZE) || defined(SANSA_E200V2)
+#define USB_PIN 3
+#endif
+
+#ifdef USB_PIN /* TODO : remove this check when we'll have an USB driver */
+ ldr r0, =GPIOA
+ mov r1, #0
+ str r1, [r0, #0x400]
+ ldr r1, [r0, #(4*(1<<USB_PIN))]
+ cmp r1, #0
+ bne boot_of
+#endif
+
+ /* Here are model specific tests, for dual boot without a computer */
+ /* All models use left button */
+ /* /!\ Right button for c200v2 (left button is unkwown) */
+
+#ifdef SANSA_CLIP
+.set row, (1<<5) /* enable output on C5 */
+.set col, (1<<0) /* read keyscan column B0 */
+
+ ldr r0, =GPIOC
+ mov r1, #row
+ str r1, [r0, #0x400]
+ str r1, [r0, #(4*row)]
+
+ ldr r0, =GPIOB
+ mov r1, #0
+ str r1, [r0, #0x400]
+ ldr r1, [r0, #(4*col)]
+
+ cmp r1, #0
+ bne boot_of
+#elif defined(SANSA_CLIPV2)
+.set row, (1<<4) /* enable output on D4 */
+.set col, (1<<0) /* read keyscan column D0 */
+
+ ldr r0, =GPIOD
+ mov r1, #((1<<5)|(1<<4)|(1<<3)) /* all rows as output */
+ str r1, [r0, #0x400]
+
+ /* all rows high */
+ mov r1, #(1<<3)
+ str r1, [r0, #(4*(1<<3))]
+ mov r1, #(1<<4)
+ str r1, [r0, #(4*(1<<4))]
+ mov r1, #(1<<5)
+ str r1, [r0, #(4*(1<<5))]
+
+ mov r1, #0 /* button row low */
+ str r1, [r0, #(4*row)]
+
+ mov r1, #5 /* small delay */
+1: subs r1, r1, #1
+ bne 1b
+
+ ldr r1, [r0, #(4*col)]
+
+ cmp r1, #0
+ beq boot_of
+#elif defined(SANSA_E200V2) || defined(SANSA_FUZE)
+ ldr r0, =GPIOC
+ mov r1, #0
+ str r1, [r0, #0x400]
+ ldr r1, [r0, #0x20] /* read pin C3 */
+
+ cmp r1, #0 /* C3 = #0 means button pressed */
+ beq boot_of
+#elif defined(SANSA_C200V2)
+ /* check for RIGHT on C6, should changed to LEFT as soon as it
+ * known in which pin that is in order for consistency */
+ ldr r0, =GPIOC
+ mov r1, #0
+ str r1, [r0, #0x400] /* set pin to output */
+
+ ldr r1, [r0, #256] /* 1<<(6+2) */
+ cmp r1, #0 /* C6 low means button pressed */
+ beq boot_of
+#elif defined(SANSA_M200V4)
+.set row, (1<<5) /* enable output on A5 */
+.set col, (1<<0) /* read keyscan column A0 */
+
+ ldr r0, =GPIOA
+ mov r1, #row
+ str r1, [r0, #0x400]
+ str r1, [r0, #(4*row)]
+
+ ldr r2, [r0, #(4*col)]
+
+ /* check value read (1 means button pressed) */
+ cmp r2, #0
+ bne boot_of
+#else
+ #error No target-specific key check defined!
+#endif
+
+
+ /* The dualboot button was not held, so we boot rockbox */
+ ldr r0, ucl_rb_end /* Address of compressed image */
+ ldr r1, ucl_rb_size /* Compressed size */
+ b decompress
+
+boot_of:
+ ldr r0, ucl_of_end /* Address of compressed image */
+ ldr r1, ucl_of_size /* Compressed size */
+
+
+decompress:
+ /* At this point: */
+ /* r5 = entry point (plus one for thumb) of uclunpack function */
+ /* r3 = destination_end for copy of UCL image */
+ /* r0 = source_end for UCL image to copy */
+ /* r1 = size of UCL image to copy */
+
+ sub r4, r3, r1 /* r4 := destination_start - 1 */
+
+fw_copy:
+ ldrb r2, [r0], #-1
+ strb r2, [r3], #-1
+ cmp r3, r4 /* Stop when we reached dest_start-1 */
+ bne fw_copy
+
+ /* Call the ucl decompress function, which will branch to 0x0 */
+ /* on completion */
+ add r0, r3, #1 /* r0 := Start of compressed image */
+ /* r1 already contains compressed size */
+ mov r2, #0 /* r2 := Destination for unpacking */
+ bx r5 /* Branch to uclunpack, switching to thumb */
+
+ /* never reached : uclunpack will branch to the reset vector (0x0) */
diff --git a/rbutil/mkamsboot/nrv2e_d8.S b/rbutil/mkamsboot/dualboot/nrv2e_d8.S
index 89cb76dead..b112ab2936 100644
--- a/rbutil/mkamsboot/nrv2e_d8.S
+++ b/rbutil/mkamsboot/dualboot/nrv2e_d8.S
@@ -191,4 +191,3 @@ copy_n2e:
/*
vi:ts=8:et:nowrap
*/
-
diff --git a/rbutil/mkamsboot/extract_fw.c b/rbutil/mkamsboot/extract_fw.c
deleted file mode 100644
index e91d1f8de1..0000000000
--- a/rbutil/mkamsboot/extract_fw.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-
-extract_fw.c - extract the main firmware image from a Sansa V2 (AMS) firmware
- file
-
-Copyright (C) Dave Chapman 2008
-
-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 program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
-
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-
-/* Win32 compatibility */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-
-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);
- }
-}
-
-static uint32_t get_uint32le(unsigned char* p)
-{
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-}
-
-void usage(void)
-{
- printf("Usage: extract_fw <firmware file> <output file>\n");
-
- exit(1);
-}
-
-int main(int argc, char* argv[])
-{
- char *infile, *outfile;
- int fdin, fdout;
- off_t len;
- uint32_t n;
- unsigned char* buf;
- uint32_t firmware_size;
-
- if(argc != 3) {
- usage();
- }
-
- infile = argv[1];
- outfile = argv[2];
-
- /* Open the firmware file */
- fdin = open(infile,O_RDONLY|O_BINARY);
-
- if (fdin < 0) {
- fprintf(stderr,"[ERR] Could not open %s for reading\n",infile);
- return 1;
- }
-
- if ((len = filesize(fdin)) < 0)
- return 1;
-
- /* We will need no more memory than the total size plus the bootloader size
- padded to a boundary */
- if ((buf = malloc(len)) == NULL) {
- fprintf(stderr,"[ERR] Could not allocate buffer for input file (%d bytes)\n",(int)len);
- return 1;
- }
-
- n = read(fdin, buf, len);
-
- if (n != (uint32_t)len) {
- fprintf(stderr,"[ERR] Could not read firmware file\n");
- return 1;
- }
-
- close(fdin);
-
- /* Get the firmware size */
- firmware_size = get_uint32le(&buf[0x0c]);
-
- fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666);
-
- if (fdout < 0) {
- fprintf(stderr,"[ERR] Could not open %s for writing\n",outfile);
- return 1;
- }
-
- n = write(fdout, buf + 0x400, firmware_size);
-
- if (n != (uint32_t)firmware_size) {
- fprintf(stderr,"[ERR] Could not write firmware block\n");
- return 1;
- }
-
- /* Clean up */
- close(fdout);
- free(buf);
-
- return 0;
-}
diff --git a/rbutil/mkamsboot/md5.c b/rbutil/mkamsboot/md5.c
index 6c5e8127f9..530d8df15a 100644
--- a/rbutil/mkamsboot/md5.c
+++ b/rbutil/mkamsboot/md5.c
@@ -123,7 +123,7 @@ void md5_process( md5_context *ctx, uint8 data[64] )
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
#undef F
-
+
#define F(x,y,z) (x ^ y ^ z)
P( A, B, C, D, 5, 4, 0xFFFA3942 );
diff --git a/rbutil/mkamsboot/mkamsboot.c b/rbutil/mkamsboot/mkamsboot.c
index 65b88af994..4210d3bd7c 100644
--- a/rbutil/mkamsboot/mkamsboot.c
+++ b/rbutil/mkamsboot/mkamsboot.c
@@ -24,7 +24,17 @@
/*
-Insert a Rockbox bootloader into an AMS original firmware file.
+Insert a Rockbox bootloader into a Sansa AMS original firmware file.
+
+Layout of a Sansa AMS original firmware file:
+
+ ---------------------- 0x0
+| HEADER |
+|----------------------| 0x400
+| FIRMWARE BLOCK |
+|----------------------| 0x400 + firmware block size
+| LIBRARIES/DATA |
+ ---------------------- END
We replace the main firmware block (bytes 0x400..0x400+firmware_size)
as follows:
@@ -50,9 +60,12 @@ as follows:
This entire block fits into the space previously occupied by the main
firmware block - the space saved by compressing the OF image is used
-to store the compressed version of the Rockbox bootloader. The OF
-image is typically about 120KB, which allows us to store a Rockbox
-bootloader with an uncompressed size of about 60KB-70KB.
+to store the compressed version of the Rockbox bootloader.
+
+On version 1 firmwares, the OF image is typically about 120KB, which allows
+us to store a Rockbox bootloader with an uncompressed size of about 60KB-70KB.
+Version 2 firmwares are bigger and are stored in SDRAM (instead of IRAM).
+In both cases, the RAM we are using is mapped at offset 0x0.
mkamsboot then corrects the checksums and writes a new legal firmware
file which can be installed on the device.
@@ -65,7 +78,7 @@ end of RAM.
Then, depending on the detection of the dual-boot keypress, either the
OF image or the Rockbox image is copied to the end of RAM (just before
-the ucl unpack function) and uncompress it to the start of RAM.
+the ucl unpack function) and uncompressed to the start of RAM.
Finally, the ucl unpack function branches to address 0x0, passing
execution to the uncompressed firmware.
@@ -73,7 +86,6 @@ execution to the uncompressed firmware.
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -85,27 +97,22 @@ execution to the uncompressed firmware.
#include <ucl/ucl.h>
-/* Headers for ARM code binaries */
-#include "nrv2e_d8.h"
+#include "mkamsboot.h"
+
#include "md5.h"
-#include "dualboot_clip.h"
-#include "dualboot_e200v2.h"
-#include "dualboot_fuze.h"
-#include "dualboot_m200v4.h"
-#include "dualboot_c200v2.h"
+/* Header for ARM code binaries */
+#include "dualboot.h"
/* Win32 compatibility */
#ifndef O_BINARY
#define O_BINARY 0
#endif
-#ifndef VERSION
-#define VERSION "0.1"
-#endif
+#define VERSION "1.0"
-enum
-{
+/* Supported models */
+enum {
MODEL_UNKNOWN = -1,
MODEL_FUZE = 0,
MODEL_CLIP,
@@ -115,31 +122,31 @@ enum
MODEL_C200V2,
};
-static const char* model_names[] =
-{
+/* Descriptive name of these models */
+static const char* model_names[] = {
"Fuze",
"Clip",
- "Clip V2",
+ "Clip v2",
"e200 v2",
"m200 v4",
"c200 v2"
};
-static const unsigned char* bootloaders[] =
-{
+/* Dualboot functions for these models */
+static const unsigned char* bootloaders[] = {
dualboot_fuze,
dualboot_clip,
- NULL,
+ dualboot_clipv2,
dualboot_e200v2,
dualboot_m200v4,
dualboot_c200v2,
};
-static const int bootloader_sizes[] =
-{
+/* Size of dualboot functions for these models */
+static const int bootloader_sizes[] = {
sizeof(dualboot_fuze),
sizeof(dualboot_clip),
- 0,
+ sizeof(dualboot_clipv2),
sizeof(dualboot_e200v2),
sizeof(dualboot_m200v4),
sizeof(dualboot_c200v2),
@@ -147,11 +154,10 @@ static const int bootloader_sizes[] =
/* Model names used in the Rockbox header in ".sansa" files - these match the
-add parameter to the "scramble" tool */
-static const char* rb_model_names[] =
-{
+static const char* rb_model_names[] = {
"fuze",
"clip",
- NULL,
+ "clv2",
"e2v2",
"m2v4",
"c2v2",
@@ -159,11 +165,10 @@ static const char* rb_model_names[] =
/* Model numbers used to initialise the checksum in the Rockbox header in
".sansa" files - these are the same as MODEL_NUMBER in config-target.h */
-static const int rb_model_num[] =
-{
+static const int rb_model_num[] = {
43,
40,
- 0,
+ 60,
41,
42,
44
@@ -172,7 +177,7 @@ static const int rb_model_num[] =
struct md5sums {
int model;
char *version;
- int fw_version;
+ int fw_version; /* version 2 is used in Clipv2 and Fuzev2 firmwares */
char *md5;
};
@@ -181,27 +186,32 @@ struct md5sums {
static struct md5sums sansasums[] = {
/* NOTE: Different regional versions of the firmware normally only
differ in the filename - the md5sums are identical */
- { MODEL_E200V2, "3.01.11", 1, "e622ca8cb6df423f54b8b39628a1f0a3" },
- { MODEL_E200V2, "3.01.14", 1, "2c1d0383fc3584b2cc83ba8cc2243af6" },
- { MODEL_E200V2, "3.01.16", 1, "12563ad71b25a1034cf2092d1e0218c4" },
-
- { MODEL_FUZE, "1.01.11", 1, "cac8ffa03c599330ac02c4d41de66166" },
- { MODEL_FUZE, "1.01.15", 1, "df0e2c1612727f722c19a3c764cff7f2" },
- { MODEL_FUZE, "1.01.22", 1, "5aff5486fe8dd64239cc71eac470af98" },
- { MODEL_FUZE, "1.02.26", 1, "7c632c479461c48c8833baed74eb5e4f" },
-
- { MODEL_C200V2, "3.02.05", 1, "b6378ebd720b0ade3fad4dc7ab61c1a5" },
-
- { MODEL_M200V4, "4.00.45", 1, "82e3194310d1514e3bbcd06e84c4add3" },
- { MODEL_M200V4, "4.01.08-A", 1, "fc9dd6116001b3e6a150b898f1b091f0" },
- { MODEL_M200V4, "4.01.08-E", 1, "d3fb7d8ec8624ee65bc99f8dab0e2369" },
-
- { MODEL_CLIP, "1.01.17", 1, "12caad785d506219d73f538772afd99e" },
- { MODEL_CLIP, "1.01.18", 1, "d720b266bd5afa38a198986ef0508a45" },
- { MODEL_CLIP, "1.01.20", 1, "236d8f75189f468462c03f6d292cf2ac" },
- { MODEL_CLIP, "1.01.29", 1, "c12711342169c66e209540cd1f27cd26" },
- { MODEL_CLIP, "1.01.30", 1, "f2974d47c536549c9d8259170f1dbe4d" },
- { MODEL_CLIP, "1.01.32", 1, "d835d12342500732ffb9c4ee54abec15" },
+
+ /* model version fw_version md5 */
+ { MODEL_E200V2, "3.01.11", 1, "e622ca8cb6df423f54b8b39628a1f0a3" },
+ { MODEL_E200V2, "3.01.14", 1, "2c1d0383fc3584b2cc83ba8cc2243af6" },
+ { MODEL_E200V2, "3.01.16", 1, "12563ad71b25a1034cf2092d1e0218c4" },
+
+ { MODEL_FUZE, "1.01.11", 1, "cac8ffa03c599330ac02c4d41de66166" },
+ { MODEL_FUZE, "1.01.15", 1, "df0e2c1612727f722c19a3c764cff7f2" },
+ { MODEL_FUZE, "1.01.22", 1, "5aff5486fe8dd64239cc71eac470af98" },
+ { MODEL_FUZE, "1.02.26", 1, "7c632c479461c48c8833baed74eb5e4f" },
+
+ { MODEL_C200V2, "3.02.05", 1, "b6378ebd720b0ade3fad4dc7ab61c1a5" },
+
+ { MODEL_M200V4, "4.00.45", 1, "82e3194310d1514e3bbcd06e84c4add3" },
+ { MODEL_M200V4, "4.01.08-A", 1, "fc9dd6116001b3e6a150b898f1b091f0" },
+ { MODEL_M200V4, "4.01.08-E", 1, "d3fb7d8ec8624ee65bc99f8dab0e2369" },
+
+ { MODEL_CLIP, "1.01.17", 1, "12caad785d506219d73f538772afd99e" },
+ { MODEL_CLIP, "1.01.18", 1, "d720b266bd5afa38a198986ef0508a45" },
+ { MODEL_CLIP, "1.01.20", 1, "236d8f75189f468462c03f6d292cf2ac" },
+ { MODEL_CLIP, "1.01.29", 1, "c12711342169c66e209540cd1f27cd26" },
+ { MODEL_CLIP, "1.01.30", 1, "f2974d47c536549c9d8259170f1dbe4d" },
+ { MODEL_CLIP, "1.01.32", 1, "d835d12342500732ffb9c4ee54abec15" },
+
+ { MODEL_CLIPV2, "2.01.16", 2, "c57fb3fcbe07c2c9b360f060938f80cb" },
+ { MODEL_CLIPV2, "2.01.32", 2, "0ad3723e52022509089d938d0fbbf8c5" }
};
#define NUM_MD5S (sizeof(sansasums)/sizeof(sansasums[0]))
@@ -209,7 +219,7 @@ static struct md5sums sansasums[] = {
static off_t filesize(int fd) {
struct stat buf;
- if (fstat(fd,&buf) < 0) {
+ if (fstat(fd, &buf) < 0) {
perror("[ERR] Checking filesize of input file");
return -1;
} else {
@@ -217,30 +227,26 @@ static off_t filesize(int fd) {
}
}
-static uint32_t get_uint32le(unsigned char* p)
-{
+static uint32_t get_uint32le(unsigned char* p) {
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
-static uint32_t get_uint32be(unsigned char* p)
-{
+static uint32_t get_uint32be(unsigned char* p) {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
-static void put_uint32le(unsigned char* p, uint32_t x)
-{
+static void put_uint32le(unsigned char* p, uint32_t x) {
p[0] = x & 0xff;
p[1] = (x >> 8) & 0xff;
p[2] = (x >> 16) & 0xff;
p[3] = (x >> 24) & 0xff;
}
-void calc_MD5(unsigned char* buf, int len, char *md5str)
-{
+void calc_MD5(unsigned char* buf, int len, char *md5str) {
int i;
md5_context ctx;
unsigned char md5sum[16];
-
+
md5_starts(&ctx);
md5_update(&ctx, buf, len);
md5_finish(&ctx, md5sum);
@@ -249,9 +255,8 @@ void calc_MD5(unsigned char* buf, int len, char *md5str)
sprintf(md5str + 2*i, "%02x", md5sum[i]);
}
-
-static uint32_t calc_checksum(unsigned char* buf, uint32_t n)
-{
+/* Calculate a simple checksum used in Sansa Original Firmwares */
+static uint32_t calc_checksum(unsigned char* buf, uint32_t n) {
uint32_t sum = 0;
uint32_t i;
@@ -261,10 +266,8 @@ static uint32_t calc_checksum(unsigned char* buf, uint32_t n)
return sum;
}
-static int get_model(int model_id)
-{
- switch(model_id)
- {
+static int get_model(int model_id) {
+ switch(model_id) {
case 0x1e:
return MODEL_FUZE;
case 0x22:
@@ -282,9 +285,8 @@ static int get_model(int model_id)
return MODEL_UNKNOWN;
}
-
-static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
-{
+/* Compress using nrv2e algorithm : Thumb decompressor fits in 168 bytes ! */
+static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize) {
int maxsize;
unsigned char* outbuf;
int r;
@@ -295,10 +297,9 @@ static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
/* Allocate some memory for the output buffer */
outbuf = malloc(maxsize);
- if (outbuf == NULL) {
+ if (outbuf == NULL)
return NULL;
- }
-
+
r = ucl_nrv2e_99_compress(
(const ucl_bytep) inbuf,
(ucl_uint) insize,
@@ -306,8 +307,7 @@ static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
(ucl_uintp) outsize,
0, 10, NULL, NULL);
- if (r != UCL_E_OK || *outsize > maxsize)
- {
+ if (r != UCL_E_OK || *outsize > maxsize) {
/* this should NEVER happen, and implies memory corruption */
fprintf(stderr, "internal error - compression failed: %d\n", r);
free(outbuf);
@@ -317,42 +317,105 @@ static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
return outbuf;
}
-static unsigned char* load_file(char* filename, off_t* bufsize)
-{
+#define ERROR(format, ...) \
+ do { \
+ snprintf(errstr, errstrsize, format, __VA_ARGS__); \
+ goto error; \
+ } while(0)
+
+/* Loads a Sansa AMS Original Firmware file into memory */
+unsigned char* load_of_file(
+ char* filename, off_t* bufsize, char* md5sum, int* model,
+ int* fw_version, int* firmware_size, unsigned char** of_packed,
+ int* of_packedsize, char* errstr, int errstrsize
+) {
int fd;
- unsigned char* buf;
+ unsigned char* buf =NULL;
off_t n;
+ unsigned int i=0;
+ uint32_t checksum;
+ int model_id;
+ unsigned int last_word;
fd = open(filename, O_RDONLY|O_BINARY);
if (fd < 0)
- {
- fprintf(stderr,"[ERR] Could not open %s for reading\n",filename);
- return NULL;
- }
+ ERROR("[ERR] Could not open %s for reading\n", filename);
*bufsize = filesize(fd);
buf = malloc(*bufsize);
- if (buf == NULL) {
- fprintf(stderr,"[ERR] Could not allocate memory for %s\n",filename);
- return NULL;
- }
+ if (buf == NULL)
+ ERROR("[ERR] Could not allocate memory for %s\n", filename);
n = read(fd, buf, *bufsize);
- if (n != *bufsize) {
- fprintf(stderr,"[ERR] Could not read file %s\n",filename);
- return NULL;
+ if (n != *bufsize)
+ ERROR("[ERR] Could not read file %s\n", filename);
+
+ /* check the file */
+
+ /* Calculate MD5 checksum of OF */
+ calc_MD5(buf, *bufsize, md5sum);
+
+ while ((i < NUM_MD5S) && (strcmp(sansasums[i].md5, md5sum) != 0))
+ i++;
+
+ if (i < NUM_MD5S) {
+ *model = sansasums[i].model;
+ *fw_version = sansasums[i].fw_version;
+ } else {
+ fprintf(stderr, "[WARN] ****** Original firmware unknown ******\n");
+ if (get_uint32le(&buf[0x204])==0x0000f000) {
+ *fw_version = 2;
+ model_id = buf[0x219];
+ } else {
+ *fw_version = 1;
+ model_id = buf[0x215];
+ }
+
+ *model = get_model(model_id);
+
+ if (*model == MODEL_UNKNOWN)
+ ERROR("[ERR] Unknown firmware - model id 0x%02x\n", model_id);
}
+ /* TODO: Do some more sanity checks on the OF image. Some images (like
+ m200v4) dont have a checksum at the end, only padding (0xdeadbeef). */
+ last_word = *bufsize - 4;
+ checksum = get_uint32le(buf + last_word);
+ if (checksum != 0xefbeadde && checksum != calc_checksum(buf, last_word))
+ ERROR("%s", "[ERR] Whole file checksum failed\n");
+
+ if (bootloaders[*model] == NULL)
+ ERROR("[ERR] Unsupported model - \"%s\"\n", model_names[*model]);
+
+
+ /* Get the firmware size */
+ if (*fw_version == 1)
+ *firmware_size = get_uint32le(&buf[0x0c]);
+ else /* fw_version == 2 */
+ *firmware_size = get_uint32le(&buf[0x10]);
+
+ /* Compress the original firmware image */
+ *of_packed = uclpack(buf + 0x400, *firmware_size, of_packedsize);
+ if (*of_packed == NULL)
+ ERROR("[ERR] Could not compress %s\n", filename);
+
return buf;
-}
+error:
+ free(buf);
+ return NULL;
+}
-static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsize)
-{
+/* Loads a rockbox bootloader file into memory */
+unsigned char* load_rockbox_file(
+ char* filename, int model, int* bufsize, int* rb_packedsize,
+ char* errstr, int errstrsize
+) {
int fd;
- unsigned char* buf;
+ unsigned char* buf = NULL;
+ unsigned char* packed = NULL;
unsigned char header[8];
uint32_t sum;
off_t n;
@@ -360,39 +423,28 @@ static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsiz
fd = open(filename, O_RDONLY|O_BINARY);
if (fd < 0)
- {
- fprintf(stderr,"[ERR] Could not open %s for reading\n",filename);
- return NULL;
- }
+ ERROR("[ERR] Could not open %s for reading\n", filename);
/* Read Rockbox header */
n = read(fd, header, sizeof(header));
- if (n != sizeof(header)) {
- fprintf(stderr,"[ERR] Could not read file %s\n",filename);
- return NULL;
- }
+ if (n != sizeof(header))
+ ERROR("[ERR] Could not read file %s\n", filename);
/* Check for correct model string */
- if (memcmp(rb_model_names[model],header + 4,4)!=0) {
- fprintf(stderr,"[ERR] Model name \"%s\" not found in %s\n",
- rb_model_names[model],filename);
- return NULL;
- }
+ if (memcmp(rb_model_names[model], header + 4, 4)!=0)
+ ERROR("[ERR] Model name \"%s\" not found in %s\n",
+ rb_model_names[model], filename);
*bufsize = filesize(fd) - sizeof(header);
buf = malloc(*bufsize);
- if (buf == NULL) {
- fprintf(stderr,"[ERR] Could not allocate memory for %s\n",filename);
- return NULL;
- }
+ if (buf == NULL)
+ ERROR("[ERR] Could not allocate memory for %s\n", filename);
n = read(fd, buf, *bufsize);
- if (n != *bufsize) {
- fprintf(stderr,"[ERR] Could not read file %s\n",filename);
- return NULL;
- }
+ if (n != *bufsize)
+ ERROR("[ERR] Could not read file %s\n", filename);
/* Check checksum */
sum = rb_model_num[model];
@@ -401,176 +453,36 @@ static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsiz
sum += buf[i];
}
- if (sum != get_uint32be(header)) {
- fprintf(stderr,"[ERR] Checksum mismatch in %s\n",filename);
- return NULL;
- }
- return buf;
-}
-
-
-int main(int argc, char* argv[])
-{
- char *infile, *bootfile, *outfile;
- int fdout;
- off_t len;
- uint32_t n;
- unsigned char* buf;
- int firmware_size;
- off_t bootloader_size;
- uint32_t sum,filesum;
- uint8_t model_id;
- int model;
- uint32_t i;
- unsigned char* of_packed;
- int of_packedsize;
- unsigned char* rb_unpacked;
- unsigned char* rb_packed;
- int rb_packedsize;
- int fw_version;
- int totalsize;
- unsigned char* p;
- uint32_t checksum;
- char md5sum[33]; /* 32 hex digits, plus terminating zero */
-
- fprintf(stderr,"mkamsboot v" VERSION " - (C) Dave Chapman and Rafaël Carré 2008\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");
-
- if(argc != 4) {
- printf("Usage: mkamsboot <firmware file> <boot file> <output file>\n\n");
- return 1;
- }
-
- infile = argv[1];
- bootfile = argv[2];
- outfile = argv[3];
-
- /* Load original firmware file */
- buf = load_file(infile, &len);
-
- if (buf == NULL) {
- fprintf(stderr,"[ERR] Could not load %s\n",infile);
- return 1;
- }
-
- /* Calculate MD5 checksum of OF */
- calc_MD5(buf, len, md5sum);
+ if (sum != get_uint32be(header))
+ ERROR("[ERR] Checksum mismatch in %s\n", filename);
- fprintf(stderr,"[INFO] MD5 sum - %s\n",md5sum);
+ packed = uclpack(buf, *bufsize, rb_packedsize);
+ if(packed == NULL)
+ ERROR("[ERR] Could not compress %s\n", filename);
- i = 0;
- while ((i < NUM_MD5S) && (strcmp(sansasums[i].md5, md5sum) != 0))
- i++;
+ free(buf);
+ return packed;
- if (i < NUM_MD5S) {
- model = sansasums[i].model;
- fw_version = sansasums[i].fw_version;
- fprintf(stderr,"[INFO] Original firmware MD5 checksum match - %s %s\n",
- model_names[model], sansasums[i].version);
- } else {
- if (get_uint32le(&buf[0x204])==0x0000f000) {
- fw_version = 2;
- model_id = buf[0x219];
- } else {
- fw_version = 1;
- model_id = buf[0x215];
- }
-
- model = get_model(model_id);
-
-#if 0
- /* if you are a tester this info might help */
- fprintf(stderr,"[WARN] ****** Original firmware unknown ******\n");
- if (model == MODEL_UNKNOWN) {
- fprintf(stderr,"[ERR] Unknown firmware - model id 0x%02x\n",
- model_id);
- free(buf);
- return 1;
- }
-#else
- /* else you don't want to brick your player */
- fprintf(stderr, "[ERR] Original firmware untested - aborting\n");
- free(buf);
- return 1;
-#endif
- }
-
-
- /* TODO: Do some more sanity checks on the OF image. Some images (like
- m200v4) dont have a checksum at the end, only padding (0xdeadbeef). */
- checksum = get_uint32le(buf + len - 4);
- if (checksum != 0xefbeadde && checksum != calc_checksum(buf, len - 4)) {
-
- fprintf(stderr,"[ERR] Whole file checksum failed - %s\n",infile);
- free(buf);
- return 1;
- }
-
- if (bootloaders[model] == NULL) {
- fprintf(stderr,"[ERR] Unsupported model - \"%s\"\n",model_names[model]);
- free(buf);
- return 1;
- }
-
- /* Load bootloader file */
- rb_unpacked = load_rockbox_file(bootfile, model, &bootloader_size);
- if (rb_unpacked == NULL) {
- fprintf(stderr,"[ERR] Could not load %s\n",bootfile);
- free(buf);
- return 1;
- }
-
- printf("[INFO] Patching %s firmware\n",model_names[model]);
-
- /* Get the firmware size */
- firmware_size = get_uint32le(&buf[0x0c]);
-
- /* Compress the original firmware image */
- of_packed = uclpack(buf + 0x400, firmware_size, &of_packedsize);
- if (of_packed == NULL) {
- fprintf(stderr,"[ERR] Could not compress original firmware\n");
- free(buf);
- free(rb_unpacked);
- return 1;
- }
-
- rb_packed = uclpack(rb_unpacked, bootloader_size, &rb_packedsize);
- if (rb_packed == NULL) {
- fprintf(stderr,"[ERR] Could not compress %s\n",bootfile);
- free(buf);
- free(rb_unpacked);
- free(of_packed);
- return 1;
- }
-
- /* We are finished with the unpacked version of the bootloader */
- free(rb_unpacked);
-
- fprintf(stderr,"[INFO] Original firmware size: %d bytes\n",firmware_size);
- fprintf(stderr,"[INFO] Packed OF size: %d bytes\n",of_packedsize);
- fprintf(stderr,"[INFO] Bootloader size: %d bytes\n",(int)bootloader_size);
- fprintf(stderr,"[INFO] Packed bootloader size: %d bytes\n",rb_packedsize);
- fprintf(stderr,"[INFO] Dual-boot function size: %d bytes\n",bootloader_sizes[model]);
- fprintf(stderr,"[INFO] UCL unpack function size: %d bytes\n",sizeof(nrv2e_d8));
-
- totalsize = bootloader_sizes[model] + sizeof(nrv2e_d8) + of_packedsize +
- rb_packedsize;
+error:
+ free(buf);
+ return NULL;
+}
- fprintf(stderr,"[INFO] Total size of new image: %d bytes\n",totalsize);
+#undef ERROR
- if (totalsize > firmware_size) {
- fprintf(stderr,"[ERR] No room to insert bootloader, aborting\n");
- free(buf);
- free(rb_unpacked);
- free(of_packed);
- return 1;
- }
+/* Patches a Sansa AMS Original Firmware file */
+void patch_firmware(
+ int model, int fw_version, int firmware_size, unsigned char* buf,
+ int len, unsigned char* of_packed, int of_packedsize,
+ unsigned char* rb_packed, int rb_packedsize
+) {
+ unsigned char *p;
+ uint32_t sum, filesum;
+ unsigned int i;
/* Zero the original firmware area - not needed, but helps debugging */
memset(buf + 0x400, 0, firmware_size);
-
/* Insert dual-boot bootloader at offset 0 */
memcpy(buf + 0x400, bootloaders[model], bootloader_sizes[model]);
@@ -589,7 +501,7 @@ int main(int argc, char* argv[])
p -= rb_packedsize;
memcpy(p, rb_packed, rb_packedsize);
- /* Write the locations of the various images to the variables at the
+ /* Write the locations of the various images to the variables at the
start of the dualboot image - we save the location of the last byte
in each image, along with the size in bytes */
@@ -602,19 +514,18 @@ int main(int argc, char* argv[])
put_uint32le(&buf[0x42c], of_packedsize);
/* Compressed Rockbox image */
- put_uint32le(&buf[0x430], firmware_size - sizeof(nrv2e_d8) - of_packedsize - 1);
+ put_uint32le(&buf[0x430], firmware_size - sizeof(nrv2e_d8) - of_packedsize
+ - 1);
put_uint32le(&buf[0x434], rb_packedsize);
/* Update the firmware block checksum */
- sum = calc_checksum(buf + 0x400,firmware_size);
+ sum = calc_checksum(buf + 0x400, firmware_size);
if (fw_version == 1) {
put_uint32le(&buf[0x04], sum);
put_uint32le(&buf[0x204], sum);
} else {
- /* TODO: Verify that this is correct for the v2 firmware */
-
put_uint32le(&buf[0x08], sum);
put_uint32le(&buf[0x208], sum);
@@ -629,29 +540,130 @@ int main(int argc, char* argv[])
filesum += get_uint32le(&buf[i]);
put_uint32le(buf + len - 4, filesum);
+}
+/* returns size of new firmware block */
+int total_size(int model, int rb_packedsize, int of_packedsize) {
+ return bootloader_sizes[model] + sizeof(nrv2e_d8) + of_packedsize +
+ rb_packedsize;
+}
+
+#ifndef LIB
+/* standalone executable */
+int main(int argc, char* argv[]) {
+ char *infile, *bootfile, *outfile;
+ int fdout;
+ off_t len;
+ uint32_t n;
+ unsigned char* buf;
+ int firmware_size;
+ int bootloader_size;
+ int model;
+ unsigned char* of_packed;
+ int of_packedsize;
+ unsigned char* rb_packed;
+ int rb_packedsize;
+ int fw_version;
+ int totalsize;
+ char md5sum[33]; /* 32 hex digits, plus terminating zero */
+ char errstr[200];
+
+ fprintf(stderr,
+"mkamsboot v" VERSION " - (C) Dave Chapman and Rafaël Carré 2008\n"
+"This is free software; see the source for copying conditions. There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+"\n");
+
+ if(argc != 4) {
+ printf("Usage: mkamsboot <firmware file> <boot file> <output file>\n");
+ return 1;
+ }
+
+ infile = argv[1];
+ bootfile = argv[2];
+ outfile = argv[3];
+
+ /* Load original firmware file */
+ buf = load_of_file(infile, &len, md5sum, &model, &fw_version,
+ &firmware_size, &of_packed, &of_packedsize, errstr, sizeof(errstr));
+
+ if (buf == NULL) {
+ fprintf(stderr, "%s", errstr);
+ fprintf(stderr, "[ERR] Could not load %s\n", infile);
+ return 1;
+ }
+
+ fprintf(stderr, "[INFO] Original firmware MD5 checksum match - %s\n",
+ model_names[model]);
+
+
+ /* Load bootloader file */
+ rb_packed = load_rockbox_file(bootfile, model, &bootloader_size,
+ &rb_packedsize, errstr, sizeof(errstr));
+ if (rb_packed == NULL) {
+ fprintf(stderr, "%s", errstr);
+ fprintf(stderr, "[ERR] Could not load %s\n", bootfile);
+ free(buf);
+ free(of_packed);
+ return 1;
+ }
+
+ printf("[INFO] Patching %s firmware\n", model_names[model]);
+
+ fprintf(stderr, "[INFO] Original firmware size: %d bytes\n",
+ firmware_size);
+ fprintf(stderr, "[INFO] Packed OF size: %d bytes\n",
+ of_packedsize);
+ fprintf(stderr, "[INFO] Bootloader size: %d bytes\n",
+ (int)bootloader_size);
+ fprintf(stderr, "[INFO] Packed bootloader size: %d bytes\n",
+ rb_packedsize);
+ fprintf(stderr, "[INFO] Dual-boot function size: %d bytes\n",
+ bootloader_sizes[model]);
+ fprintf(stderr, "[INFO] UCL unpack function size: %d bytes\n",
+ sizeof(nrv2e_d8));
+
+ totalsize = total_size(model, of_packedsize, rb_packedsize);
+
+ fprintf(stderr, "[INFO] Total size of new image: %d bytes\n", totalsize);
+
+ if (totalsize > firmware_size) {
+ fprintf(stderr, "[ERR] No room to insert bootloader, aborting\n");
+ free(buf);
+ free(of_packed);
+ free(rb_packed);
+ return 1;
+ }
+
+ patch_firmware(model, fw_version, firmware_size, buf, len, of_packed,
+ of_packedsize, rb_packed, rb_packedsize);
/* Write the new firmware */
- fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666);
+ fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
if (fdout < 0) {
- fprintf(stderr,"[ERR] Could not open %s for writing\n",outfile);
+ fprintf(stderr, "[ERR] Could not open %s for writing\n", outfile);
+ free(buf);
+ free(of_packed);
+ free(rb_packed);
return 1;
}
n = write(fdout, buf, len);
if (n != (unsigned)len) {
- fprintf(stderr,"[ERR] Could not write firmware file\n");
+ fprintf(stderr, "[ERR] Could not write firmware file\n");
+ free(buf);
+ free(of_packed);
+ free(rb_packed);
return 1;
}
close(fdout);
-
- fprintf(stderr," *****************************************************************************\n");
- fprintf(stderr," *** THIS CODE IS UNTESTED - DO NOT USE IF YOU CAN NOT RECOVER YOUR DEVICE ***\n");
- fprintf(stderr," *****************************************************************************\n");
+ free(buf);
+ free(of_packed);
+ free(rb_packed);
return 0;
-
}
+#endif
diff --git a/rbutil/mkamsboot/mkamsboot.h b/rbutil/mkamsboot/mkamsboot.h
new file mode 100644
index 0000000000..e2de46c9b8
--- /dev/null
+++ b/rbutil/mkamsboot/mkamsboot.h
@@ -0,0 +1,124 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * mkamsboot.h - a tool for merging bootloader code into an Sansa V2
+ * (AMS) firmware file
+ *
+ * Copyright (C) 2008 Dave Chapman
+ *
+ * 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 MKAMSBOOT_H
+#define MKAMSBOOT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+
+/* load_rockbox_file()
+ *
+ * Loads a rockbox bootloader file into memory
+ *
+ * ARGUMENTS
+ *
+ * filename : bootloader file to load
+ * model : a 4 characters string representing the Sansa model
+ * ("fuze", "clip", "e2v2", "m2v4", or "c2v2")
+ * bootloader_size : set to the uncompressed bootloader size
+ * rb_packed_size : set to the size of compressed bootloader
+ * errstr : provided buffer to store an eventual error
+ * errstrsize : size of provided error buffer
+ *
+ * RETURN VALUE
+ * pointer to allocated memory containing the content of compressed bootloader
+ * or NULL in case of error (errstr will hold a description of the error)
+ */
+
+unsigned char* load_rockbox_file(
+ char* filename, int model, int* bootloader_size, int* rb_packedsize,
+ char* errstr, int errstrsize);
+
+
+/* load_of_file()
+ *
+ * Loads a Sansa AMS Original Firmware file into memory
+ *
+ * ARGUMENTS
+ *
+ * filename : firmware file to load
+ * bufsize : set to firmware file size
+ * md5sum : set to file md5sum, must be at least 33 bytes long
+ * model : set to firmware model (MODEL_XXX)
+ * fw_version : set to firmware format version (1 or 2)
+ * firmware_size : set to firmware block's size
+ * of_packed : pointer to allocated memory containing the compressed
+ * original firmware block
+ * of_packedsize : size of compressed original firmware block
+ * errstr : provided buffer to store an eventual error
+ * errstrsize : size of provided error buffer
+ *
+ * RETURN VALUE
+ * pointer to allocated memory containing the content of Original Firmware
+ * or NULL in case of error (errstr will hold a description of the error)
+ */
+
+unsigned char* load_of_file(
+ char* filename, off_t* bufsize, char* md5sum, int* model,
+ int* fw_version, int* firmware_size, unsigned char** of_packed,
+ int* of_packedsize, char* errstr, int errstrsize);
+
+
+/* patch_firmware()
+ *
+ * Patches a Sansa AMS Original Firmware file
+ *
+ * ARGUMENTS
+ *
+ * model : firmware model (MODEL_XXX)
+ * fw_version : firmware format version (1 or 2)
+ * firmware_size : size of uncompressed original firmware block
+ * buf : pointer to original firmware file
+ * len : size of original firmware file
+ * of_packed : pointer to compressed original firmware block
+ * of_packedsize : size of compressed original firmware block
+ * rb_packed : pointer to compressed rockbox bootloader
+ * rb_packed_size : size of compressed rockbox bootloader
+ */
+
+void patch_firmware(
+ int model, int fw_version, int firmware_size, unsigned char* buf,
+ int len, unsigned char* of_packed, int of_packedsize,
+ unsigned char* rb_packed, int rb_packedsize);
+
+
+/* total_size()
+ *
+ * Calculates the size of the new firmware block
+ *
+ * ARGUMENTS
+ *
+ * model : firmware model (MODEL_XXX)
+ * rb_packed_size : size of compressed rockbox bootloader
+ * of_packedsize : size of compressed original firmware block
+ *
+ * RETURN VALUE
+ * Size of new firmware block
+*/
+
+int total_size(int model, int rb_packedsize, int of_packedsize);
+
+#endif