summaryrefslogtreecommitdiff
path: root/rbutil
diff options
context:
space:
mode:
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 @@
1CC=gcc
2
3# We use the UCL code available in the Rockbox tools/ directory 1# We use the UCL code available in the Rockbox tools/ directory
4CFLAGS=-I../../tools/ucl/include 2CFLAGS=-I../../tools/ucl/include -Wall
5LIBUCL=../../tools/ucl/src/libucl.a 3LIBUCL=../../tools/ucl/src/libucl.a
6 4
7# Edit the following variables (plus copy/paste another set of rules) when 5ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
8# adding a new target. mkamsboot.c also needs to be edited to refer to these 6OUTPUT=mkamsboot.exe
9# new images. 7CFLAGS+=-mno-cygwin
10 8else
11BOOTIMAGES = dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o 9ifeq ($(findstring MINGW,$(shell uname)),MINGW)
12BOOTHEADERS = dualboot_clip.h dualboot_e200v2.h dualboot_c200v2.h dualboot_m200v4.h dualboot_fuze.h 10OUTPUT=mkamsboot.exe
13 11else
14CLIPFILES = dualboot_clip.arm-o dualboot_clip.o dualboot_clip.c dualboot_clip.h 12ifeq ($(findstring mingw,$(CC)),mingw)
15 13OUTPUT=mkamsboot.exe
16E200V2FILES = dualboot_e200v2.arm-o dualboot_e200v2.o dualboot_e200v2.c \ 14else
17 dualboot_e200v2.h 15OUTPUT=mkamsboot
18 16endif
19M200V4FILES = dualboot_m200v4.arm-o dualboot_m200v4.o dualboot_m200v4.arm-bin \ 17endif
20 dualboot_m200v4.c dualboot_m200v4.h 18endif
21 19
22C200V2FILES = dualboot_c200v2.arm-o dualboot_c200v2.o dualboot_c200v2.c \ 20CC?= gcc
23 dualboot_c200v2.h 21
24 22all: $(OUTPUT)
25FUZEFILES = dualboot_fuze.arm-o dualboot_fuze.o dualboot_fuze.c dualboot_fuze.h
26
27all: mkamsboot
28
29# Dualboot bootloaders
30
31dualboot_clip.arm-o: dualboot.S
32 arm-elf-gcc -DSANSA_CLIP -c -o dualboot_clip.arm-o dualboot.S
33
34dualboot_fuze.arm-o: dualboot.S
35 arm-elf-gcc -DSANSA_FUZE -c -o dualboot_fuze.arm-o dualboot.S
36
37dualboot_e200v2.arm-o: dualboot.S
38 arm-elf-gcc -DSANSA_E200V2 -c -o dualboot_e200v2.arm-o dualboot.S
39
40dualboot_m200v4.arm-o: dualboot.S
41 arm-elf-gcc -DSANSA_M200V4 -c -o dualboot_m200v4.arm-o dualboot.S
42
43dualboot_c200v2.arm-o: dualboot.S
44 arm-elf-gcc -DSANSA_C200V2 -c -o dualboot_c200v2.arm-o dualboot.S
45
46# Rules for the ucl unpack function
47nrv2e_d8.arm-o: nrv2e_d8.S
48 arm-elf-gcc -DPURE_THUMB -c -o nrv2e_d8.arm-o nrv2e_d8.S
49
50
51 23
52$(LIBUCL): 24$(LIBUCL):
53 make -C ../../tools/ucl/src libucl.a 25 make -C ../../tools/ucl/src libucl.a
54 26
27# This file can be generated in the dualboot/ directory
28dualboot.o: dualboot.c
29 $(CC) $(CFLAGS) -c -o dualboot.o dualboot.c
30
55md5.o: md5.c md5.h 31md5.o: md5.c md5.h
56 $(CC) $(CFLAGS) -c -o md5.o -W -Wall md5.c 32 $(CC) $(CFLAGS) -c -o md5.o -W -Wall md5.c
57 33
58mkamsboot.o: mkamsboot.c $(BOOTHEADERS) nrv2e_d8.h md5.h 34mkamsboot.o: mkamsboot.c dualboot.h md5.h
59 $(CC) $(CFLAGS) -c -o mkamsboot.o -W -Wall mkamsboot.c 35 $(CC) $(CFLAGS) -c -o mkamsboot.o -W -Wall mkamsboot.c
60 36
61mkamsboot: mkamsboot.o $(BOOTIMAGES) nrv2e_d8.o md5.o $(LIBUCL) 37$(OUTPUT): mkamsboot.o md5.o dualboot.o $(LIBUCL)
62 $(CC) -o mkamsboot mkamsboot.o $(BOOTIMAGES) nrv2e_d8.o md5.o $(LIBUCL) 38 $(CC) $(CFLAGS) -o $(OUTPUT) mkamsboot.o md5.o dualboot.o $(LIBUCL)
63
64# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
65# the binary code and finally convert to .c/.h for linking with mkamsboot
66
67%.arm-elf: %.arm-o
68 arm-elf-ld -e 0 -Ttext=0 -o $@ $<
69
70%.arm-bin: %.arm-elf
71 arm-elf-objcopy -O binary $< $@
72
73%.c %.h: %.arm-bin bin2c
74 ./bin2c $< $*
75
76# Generic host rule.
77%.o: %.c
78 $(CC) $(CFLAGS) -c -o $@ $<
79 39
80# Cancel the implicit .S -> .o rule 40libmkamsboot.o: mkamsboot.c dualboot.h md5.h
81%.o: %.S 41 $(CC) $(CFLAGS) -DLIB -c -o libmkamsboot.o -W -Wall mkamsboot.c
82 42
83bin2c: bin2c.c 43libmkamsboot.a: libmkamsboot.o md5.o dualboot.o
84 $(CC) -o bin2c bin2c.c 44 $(AR) ruv libmkamsboot.a libmkamsboot.o md5.o dualboot.o
85 45
86clean: 46clean:
87 rm -f mkamsboot mkamsboot.o nrv2e_d8.arm-o nrv2e_d8.arm-elf \ 47 rm -f $(OUTPUT) mkamsboot.o *~ md5.o dualboot.o \
88 nrv2e_d8.arm-bin *~ bin2c nrv2e_d8.c nrv2e_d8.h nrv2e_d8.o md5.o \ 48 libmkamsboot.o libmkamsboot.a
89 $(BOOTIMAGES) $(CLIPFILES) $(E200V2FILES) $(M200V4FILES) $(FUZEFILES) \
90 $(C200V2FILES)
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
3 3
4A tool to inject a bootloader into a Sansa V2 (AMS) firmware file. 4A tool to inject a bootloader into a Sansa V2 (AMS) firmware file.
5 5
6See comments in mkamsboot.c and dualboot.S for more information. 6
7Usage
8-----
9
10mkamsboot <firmware file> <boot file> <output file>
11
12<firmware file> is an original Sansa firmware file obtained from the Sansa
13 forums for example : http://forums.sandisk.com/sansa/?category.id=devices
14
15<boot file> is the code you want to execute (a rockbox bootloader), previously
16 scrambled with tools/scramble utility.
17
18<output file> is the resulting firmware file which you'll have to copy on your
19 Sansa player. See "Firmware filenames".
20
21
22Supported models
23----------------
24
25Sansa Clip : firmware version starting with "01."
26Sansa Clipv2: firmware version starting with "02."
27Sansa Fuze : firmware version starting with "01."
28Sansa E200v2: firmware version starting with "03."
29Sansa C200v2: firmware version starting with "03."
30Sansa M200v4: firmware version starting with "4."
31
32
33Firmware filenames
34------------------
35
36For the firmware upgrade to happen, the firmware has to be named specially:
37
38clip v2 : m30pa.bin
39clip : m300a.bin
40fuze : fuzea.bin
41e200v2 : e200pa.bin
42c200v2 : c200pa.bin
43m200v4 : m200a.bin
44
45
46Dual-Boot
47---------
48
49 The purpose of this program is to provide dual-boot between the original
50firmware and the new (rockbox) firmware.
51
52 By default the player will boot into the new firmware.
53
54 To boot into the Original Firmware, you need to press the Left key.
55 ***Note : on the c200v2 you need to press the Right key.
56
57 The player will boot into the Original Firmware as well if it is powered up by
58inserting an usb cable.
59 ***Note : on the m200v4 powering up by usb will cause booting into the new
60firmware
61
62Hacking
63-------
64
65See 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdio.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <stdlib.h>
29
30#ifndef O_BINARY
31#define O_BINARY 0
32#endif
33
34static off_t filesize(int fd)
35{
36 struct stat buf;
37
38 fstat(fd,&buf);
39 return buf.st_size;
40}
41
42static int write_cfile(const unsigned char* buf, off_t len, const char* cname)
43{
44 char filename[256];
45 FILE* fp;
46 int i;
47
48 snprintf(filename,256,"%s.c",cname);
49
50 fp = fopen(filename,"w+");
51 if (fp == NULL) {
52 fprintf(stderr,"Couldn't open %s\n",filename);
53 return -1;
54 }
55
56 fprintf(fp,"/* Generated by bin2c */\n\n");
57 fprintf(fp,"unsigned char %s[%d] = {",cname,len);
58
59 for (i=0;i<len;i++) {
60 if ((i % 16) == 0) {
61 fprintf(fp,"\n ");
62 }
63 if (i == (len-1)) {
64 fprintf(fp,"0x%02x",buf[i]);
65 } else {
66 fprintf(fp,"0x%02x, ",buf[i]);
67 }
68 }
69 fprintf(fp,"\n};\n");
70
71 fclose(fp);
72 return 0;
73}
74
75static int write_hfile(off_t len, const char* cname)
76{
77 char filename[256];
78 FILE* fp;
79
80 snprintf(filename,256,"%s.h",cname);
81 fp = fopen(filename,"w+");
82 if (fp == NULL) {
83 fprintf(stderr,"Couldn't open %s\n",filename);
84 return -1;
85 }
86
87 fprintf(fp,"/* Generated by bin2c */\n\n");
88 fprintf(fp,"extern unsigned char %s[%d];\n",cname,len);
89 fclose(fp);
90 return 0;
91}
92
93int main (int argc, char* argv[])
94{
95 char* infile;
96 char* cname;
97 int fd;
98 unsigned char* buf;
99 int len;
100 int n;
101
102 if (argc != 3) {
103 fprintf(stderr,"Usage: bin2c file cname\n");
104 return 0;
105 }
106
107 infile=argv[1];
108 cname=argv[2];
109
110 fd = open(infile,O_RDONLY|O_BINARY);
111 if (fd < 0) {
112 fprintf(stderr,"Can not open %s\n",infile);
113 return 0;
114 }
115
116 len = filesize(fd);
117
118 buf = malloc(len);
119 n = read(fd,buf,len);
120 if (n < len) {
121 fprintf(stderr,"Short read, aborting\n");
122 return 0;
123 }
124 close(fd);
125
126 if (write_cfile(buf,len,cname) < 0) {
127 return -1;
128 }
129 if (write_hfile(len,cname) < 0) {
130 return -1;
131 }
132
133 return 0;
134}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 Rafaël Carré
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22.text
23
24.set IRAM_SIZE, 0x50000
25
26.set GPIOA, 0xC80B0000
27.set GPIOB, 0xC80C0000
28.set GPIOC, 0xC80D0000
29.set GPIOD, 0xC80E0000
30.set CGU_PERI, 0xC80F0014
31
32
33/* Vectors */
34 ldr pc, =start
35.word 0
36.word 0
37.word 0
38.word 0
39.word 0
40.word 0
41.word 0
42
43/* These values are filled in by mkamsboot - don't move them from offset 0x20 */
44uclunpack_end: .word 0 /* End of the ucl_unpack function */
45uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */
46
47ucl_of_end: .word 0 /* End of the ucl-compressed OF image */
48ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */
49
50ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */
51ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */
52
53
54start:
55 /* First copy the UCL unpack function to the end of RAM */
56 ldr r0, uclunpack_end /* Source */
57 ldr r1, uclunpack_size /* Source length */
58 sub r2, r0, r1 /* Source start - 1*/
59
60 ldr r3, =(IRAM_SIZE-1) /* Destination end */
61
62uclcopy:
63 ldrb r4, [r0], #-1
64 strb r4, [r3], #-1
65 cmp r2, r0
66 bne uclcopy
67
68 add r5, r3, #2 /* r5 is entry point of copy of uclunpack */
69 /* function, plus one (for thumb mode */
70
71 /* enable gpio clock */
72 ldr r0, =CGU_PERI
73 ldr r1, [r0]
74 orr r1, r1, #(1<<16)
75 str r1, [r0]
76
77
78#ifndef SANSA_M200V4 /* this doesnt work for m200 */
79 /* we check A3 unconditionally of the model because it seems to be */
80 /* either hold, either usb on every model */
81 /* TODO: make it USB on all AMS Sansas for consistency, USB is safer too */
82
83 ldr r0, =GPIOA
84 mov r1, #0
85 str r1, [r0, #0x400]
86#ifdef SANSA_C200V2
87 ldr r1, [r0, #0x8] /* USB is A1 on C200 */
88#elif defined(SANSA_CLIP)
89 ldr r1, [r0, #0x100] /* USB is A6 on Clip */
90#else
91 ldr r1, [r0, #0x20] /* read pin A3 */
92#endif
93 cmp r1, #0
94 bne boot_of
95#endif
96
97 /* here are model specific tests, for dual boot without a computer */
98
99#ifdef SANSA_CLIP
100 /* LEFT button */
101.set row, (1<<5) /* enable output on C5 */
102 ldr r0, =GPIOC
103 mov r1, #row
104 str r1, [r0, #0x400]
105 str r1, [r0, #(4*row)]
106
107.set col, (1<<0) /* read keyscan column B0 */
108 ldr r0, =GPIOB
109 mov r1, #0
110 str r1, [r0, #0x400]
111 ldr r1, [r0, #(4*col)]
112
113 cmp r1, #0
114 bne boot_of
115#elif defined(SANSA_E200V2) || defined(SANSA_FUZE)
116 /* LEFT button */
117 ldr r0, =GPIOC
118 mov r1, #0
119 str r1, [r0, #0x400]
120 ldr r1, [r0, #0x20] /* read pin C3 */
121
122 cmp r1, #0 /* C3 = #0 means button pressed */
123 beq boot_of
124#elif defined(SANSA_C200V2)
125 /* check for RIGHT on C6, should maybe changed to LEFT as soon as it
126 * known in which pin that is in order for consistency */
127 ldr r0, =GPIOC
128 mov r1, #0
129 str r1, [r0, #0x400] /* set pin to output */
130
131 ldr r1, [r0, #256] /* 1<<(6+2) */
132 cmp r1, #0 /* C6 low means button pressed */
133 beq boot_of
134#elif defined(SANSA_M200V4)
135 /* LEFT button */
136.set row, (1<<5) /* enable output on A5 */
137 ldr r0, =GPIOA
138 mov r1, #row
139 str r1, [r0, #0x400]
140 str r1, [r0, #(4*row)]
141
142.set col, (1<<0) /* read keyscan column A0 */
143 ldr r2, [r0, #(4*col)]
144
145 /* check value read (1 means button pressed) */
146 cmp r2, #0
147 bne boot_of
148#else
149 #error No target-specific key check defined!
150#endif
151
152 /* No button was held, so we boot rockbox */
153 ldr r0, ucl_rb_end /* Address of compressed image */
154 ldr r1, ucl_rb_size /* Compressed size */
155 b decompress
156
157boot_of:
158 ldr r0, ucl_of_end /* Address of compressed image */
159 ldr r1, ucl_of_size /* Compressed size */
160
161
162decompress:
163 /* At this point: */
164 /* r5 = entry point (plus one for thumb) of uclunpack function */
165 /* r3 = destination_end for copy of UCL image */
166 /* r0 = source_end for UCL image to copy */
167 /* r1 = size of UCL image to copy */
168
169 sub r4, r3, r1 /* r4 := destination_start - 1 */
170
171fw_copy:
172 ldrb r2, [r0], #-1
173 strb r2, [r3], #-1
174 cmp r3, r4 /* Stop when we reached dest_start-1 */
175 bne fw_copy
176
177 /* Call the ucl decompress function, which will branch to 0x0 */
178 /* on completion */
179 add r0, r3, #1 /* r0 := Start of compressed image */
180 /* r1 already contains compressed size */
181 mov r2, #0 /* r2 := Destination for unpacking */
182 bx r5 /* Branch to uclunpack, switching to thumb */
183
184 /* 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 @@
1/* Generated by bin2c */
2
3unsigned char nrv2e_d8[168] = {
4 0x0f, 0x18, 0x01, 0x24, 0x65, 0x42, 0xe4, 0x07, 0x05, 0x26, 0x36, 0x02, 0x0a, 0xe0, 0x00, 0x20,
5 0x00, 0x47, 0x04, 0x78, 0x64, 0x41, 0x01, 0x30, 0x24, 0x06, 0xf7, 0x46, 0x03, 0x78, 0x01, 0x30,
6 0x13, 0x70, 0x01, 0x32, 0x24, 0x19, 0xfe, 0x46, 0xf3, 0xd0, 0xf7, 0xd2, 0x01, 0x21, 0x04, 0xe0,
7 0x01, 0x39, 0x24, 0x19, 0xfe, 0x46, 0xec, 0xd0, 0x49, 0x41, 0x24, 0x19, 0xfe, 0x46, 0xe8, 0xd0,
8 0x49, 0x41, 0x24, 0x19, 0xfe, 0x46, 0xe4, 0xd0, 0xf2, 0xd3, 0xcb, 0x1e, 0x00, 0x21, 0x08, 0xd3,
9 0x1b, 0x02, 0x05, 0x78, 0x01, 0x30, 0x1d, 0x43, 0xed, 0x43, 0xd8, 0xd0, 0x6d, 0x10, 0x13, 0xd2,
10 0x03, 0xe0, 0x24, 0x19, 0xfe, 0x46, 0xd4, 0xd0, 0x0e, 0xd2, 0x01, 0x21, 0x24, 0x19, 0xfe, 0x46,
11 0xcf, 0xd0, 0x09, 0xd2, 0x24, 0x19, 0xfe, 0x46, 0xcb, 0xd0, 0x49, 0x41, 0x24, 0x19, 0xfe, 0x46,
12 0xc7, 0xd0, 0xf7, 0xd3, 0x04, 0x31, 0x04, 0xe0, 0x24, 0x19, 0xfe, 0x46, 0xc1, 0xd0, 0x49, 0x41,
13 0x02, 0x31, 0xee, 0x42, 0x00, 0xd2, 0x01, 0x31, 0x13, 0x78, 0x53, 0x5d, 0x13, 0x70, 0x01, 0x32,
14 0x01, 0x39, 0xfa, 0xd1, 0xbe, 0xe7, 0x00, 0x00
15};
16unsigned char dualboot_clip[248] = {
17 0xd8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
18 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
21 0x01, 0x20, 0x40, 0xe0, 0x98, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
22 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x84, 0x00, 0x9f, 0xe5,
23 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x78, 0x00, 0x9f, 0xe5,
24 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x00, 0x11, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
25 0x0c, 0x00, 0x00, 0x1a, 0x64, 0x00, 0x9f, 0xe5, 0x20, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
26 0x80, 0x10, 0x80, 0xe5, 0x58, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
27 0x04, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x1a, 0x84, 0x00, 0x1f, 0xe5,
28 0x84, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x98, 0x00, 0x1f, 0xe5, 0x98, 0x10, 0x1f, 0xe5,
29 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
30 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
31 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
32 0x00, 0x00, 0x0d, 0xc8, 0x00, 0x00, 0x0c, 0xc8
33};
34unsigned char dualboot_e200v2[228] = {
35 0xc8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
39 0x01, 0x20, 0x40, 0xe0, 0x88, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
40 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x74, 0x00, 0x9f, 0xe5,
41 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x68, 0x00, 0x9f, 0xe5,
42 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
43 0x08, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
44 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x74, 0x00, 0x1f, 0xe5,
45 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x88, 0x00, 0x1f, 0xe5, 0x88, 0x10, 0x1f, 0xe5,
46 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
47 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
48 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
49 0x00, 0x00, 0x0d, 0xc8
50};
51unsigned char dualboot_c200v2[228] = {
52 0xc8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
56 0x01, 0x20, 0x40, 0xe0, 0x88, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
57 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x74, 0x00, 0x9f, 0xe5,
58 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x68, 0x00, 0x9f, 0xe5,
59 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x08, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
60 0x08, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
61 0x00, 0x11, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x74, 0x00, 0x1f, 0xe5,
62 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x88, 0x00, 0x1f, 0xe5, 0x88, 0x10, 0x1f, 0xe5,
63 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
64 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
65 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
66 0x00, 0x00, 0x0d, 0xc8
67};
68unsigned char dualboot_m200v4[204] = {
69 0xb4, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
73 0x01, 0x20, 0x40, 0xe0, 0x74, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
74 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x60, 0x00, 0x9f, 0xe5,
75 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x54, 0x00, 0x9f, 0xe5,
76 0x20, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x80, 0x10, 0x80, 0xe5, 0x04, 0x20, 0x90, 0xe5,
77 0x00, 0x00, 0x52, 0xe3, 0x02, 0x00, 0x00, 0x1a, 0x60, 0x00, 0x1f, 0xe5, 0x60, 0x10, 0x1f, 0xe5,
78 0x01, 0x00, 0x00, 0xea, 0x74, 0x00, 0x1f, 0xe5, 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x40, 0x43, 0xe0,
79 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1, 0xfb, 0xff, 0xff, 0x1a,
80 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1, 0x38, 0x00, 0x00, 0x00,
81 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8
82};
83unsigned char dualboot_fuze[228] = {
84 0xc8, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
88 0x01, 0x20, 0x40, 0xe0, 0x88, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
89 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0x74, 0x00, 0x9f, 0xe5,
90 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x68, 0x00, 0x9f, 0xe5,
91 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
92 0x08, 0x00, 0x00, 0x1a, 0x54, 0x00, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
93 0x20, 0x10, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x74, 0x00, 0x1f, 0xe5,
94 0x74, 0x10, 0x1f, 0xe5, 0x01, 0x00, 0x00, 0xea, 0x88, 0x00, 0x1f, 0xe5, 0x88, 0x10, 0x1f, 0xe5,
95 0x01, 0x40, 0x43, 0xe0, 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1,
96 0xfb, 0xff, 0xff, 0x1a, 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1,
97 0x38, 0x00, 0x00, 0x00, 0xff, 0xff, 0x04, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8,
98 0x00, 0x00, 0x0d, 0xc8
99};
100unsigned char dualboot_clipv2[272] = {
101 0xf4, 0xf0, 0x9f, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x1f, 0xe5, 0x20, 0x10, 0x1f, 0xe5,
105 0x01, 0x20, 0x40, 0xe0, 0xb4, 0x30, 0x9f, 0xe5, 0x01, 0x40, 0x50, 0xe4, 0x01, 0x40, 0x43, 0xe4,
106 0x00, 0x00, 0x52, 0xe1, 0xfb, 0xff, 0xff, 0x1a, 0x02, 0x50, 0x83, 0xe2, 0xa0, 0x00, 0x9f, 0xe5,
107 0x00, 0x10, 0x90, 0xe5, 0x01, 0x18, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x94, 0x00, 0x9f, 0xe5,
108 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5, 0x00, 0x11, 0x90, 0xe5, 0x00, 0x00, 0x51, 0xe3,
109 0x13, 0x00, 0x00, 0x1a, 0x80, 0x00, 0x9f, 0xe5, 0x38, 0x10, 0xa0, 0xe3, 0x00, 0x14, 0x80, 0xe5,
110 0x08, 0x10, 0xa0, 0xe3, 0x20, 0x10, 0x80, 0xe5, 0x10, 0x10, 0xa0, 0xe3, 0x40, 0x10, 0x80, 0xe5,
111 0x20, 0x10, 0xa0, 0xe3, 0x80, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x40, 0x10, 0x80, 0xe5,
112 0x05, 0x10, 0xa0, 0xe3, 0x01, 0x10, 0x51, 0xe2, 0xfd, 0xff, 0xff, 0x1a, 0x04, 0x10, 0x90, 0xe5,
113 0x00, 0x00, 0x51, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0xa0, 0x00, 0x1f, 0xe5, 0xa0, 0x10, 0x1f, 0xe5,
114 0x01, 0x00, 0x00, 0xea, 0xb4, 0x00, 0x1f, 0xe5, 0xb4, 0x10, 0x1f, 0xe5, 0x01, 0x40, 0x43, 0xe0,
115 0x01, 0x20, 0x50, 0xe4, 0x01, 0x20, 0x43, 0xe4, 0x04, 0x00, 0x53, 0xe1, 0xfb, 0xff, 0xff, 0x1a,
116 0x01, 0x00, 0x83, 0xe2, 0x00, 0x20, 0xa0, 0xe3, 0x15, 0xff, 0x2f, 0xe1, 0x38, 0x00, 0x00, 0x00,
117 0xff, 0xff, 0x0f, 0x00, 0x14, 0x00, 0x0f, 0xc8, 0x00, 0x00, 0x0b, 0xc8, 0x00, 0x00, 0x0e, 0xc8
118};
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 @@
1/* Generated by bin2c */
2
3extern unsigned char nrv2e_d8[168];
4extern unsigned char dualboot_clip[248];
5extern unsigned char dualboot_e200v2[228];
6extern unsigned char dualboot_c200v2[228];
7extern unsigned char dualboot_m200v4[204];
8extern unsigned char dualboot_fuze[228];
9extern 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 @@
1CC=gcc
2
3# Edit the following variables (plus copy/paste another set of rules) when
4# adding a new target. mkamsboot.c also needs to be edited to refer to these
5# new images.
6
7BOOTOBJS = nrv2e_d8.o dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o dualboot_clipv2.o
8BOOTBINS = 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
9
10all: dualboot.h
11
12dualboot.h: $(BOOTBINS)
13
14# Dualboot bootloaders
15
16dualboot_clip.o: dualboot.S
17 arm-elf-gcc -DSANSA_CLIP -c -o dualboot_clip.o dualboot.S
18
19dualboot_fuze.o: dualboot.S
20 arm-elf-gcc -DSANSA_FUZE -c -o dualboot_fuze.o dualboot.S
21
22dualboot_e200v2.o: dualboot.S
23 arm-elf-gcc -DSANSA_E200V2 -c -o dualboot_e200v2.o dualboot.S
24
25dualboot_m200v4.o: dualboot.S
26 arm-elf-gcc -DSANSA_M200V4 -c -o dualboot_m200v4.o dualboot.S
27
28dualboot_c200v2.o: dualboot.S
29 arm-elf-gcc -DSANSA_C200V2 -c -o dualboot_c200v2.o dualboot.S
30
31dualboot_clipv2.o: dualboot.S
32 arm-elf-gcc -DSANSA_CLIPV2 -c -o dualboot_clipv2.o dualboot.S
33
34# Rules for the ucl unpack function
35nrv2e_d8.o: nrv2e_d8.S
36 arm-elf-gcc -DPURE_THUMB -c -o nrv2e_d8.o nrv2e_d8.S
37
38# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
39# the binary code and finally convert to .h for building in mkamsboot
40
41%.arm-elf: %.o
42 arm-elf-ld -e 0 -Ttext=0 -o $@ $<
43
44%.arm-bin: %.arm-elf
45 arm-elf-objcopy -O binary $< $@
46
47dualboot.c dualboot.h: $(BOOTBINS) bin2c
48 ./bin2c dualboot $(BOOTBINS)
49
50bin2c: bin2c.c
51 $(CC) -o bin2c bin2c.c
52
53clean:
54 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdio.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <stdlib.h>
29
30#ifndef O_BINARY
31#define O_BINARY 0
32#endif
33
34static off_t filesize(int fd)
35{
36 struct stat buf;
37
38 fstat(fd,&buf);
39 return buf.st_size;
40}
41
42static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name)
43{
44 int i;
45
46 fprintf(fp,"unsigned char %s[%ld] = {",name,len);
47
48 for (i=0;i<len;i++) {
49 if ((i % 16) == 0) {
50 fprintf(fp,"\n ");
51 }
52 if (i == (len-1)) {
53 fprintf(fp,"0x%02x",buf[i]);
54 } else if ((i % 16) == 15) {
55 fprintf(fp,"0x%02x,",buf[i]);
56 } else {
57 fprintf(fp,"0x%02x, ",buf[i]);
58 }
59 }
60 fprintf(fp,"\n};\n");
61}
62
63int main (int argc, char* argv[])
64{
65 char* cname;
66 int i;
67 FILE *cfile, *hfile;
68 char cfilename[256], hfilename[256];
69
70 if (argc < 3) {
71 fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n");
72 return 1;
73 }
74
75 cname=argv[1];
76
77 snprintf(cfilename,256,"%s.c",cname);
78 cfile = fopen(cfilename,"w+");
79 if (cfile == NULL) {
80 fprintf(stderr,"Couldn't open %s\n",cfilename);
81 return 2;
82 }
83
84 snprintf(hfilename,256,"%s.h",cname);
85 hfile = fopen(hfilename,"w+");
86 if (hfile == NULL) {
87 fprintf(stderr,"Couldn't open %s\n",hfilename);
88 fclose(cfile);
89 return 3;
90 }
91
92 fprintf(cfile,"/* Generated by bin2c */\n\n");
93 fprintf(hfile,"/* Generated by bin2c */\n\n");
94
95 for(i=0; i < argc - 2; i++) {
96 unsigned char* buf;
97 off_t len;
98 char *ext;
99 char *array = argv[2+i];
100
101 int fd = open(array,O_RDONLY|O_BINARY);
102 if (fd < 0) {
103 fprintf(stderr,"Can not open %s\n",argv[2+i]);
104 fclose(cfile);
105 fclose(hfile);
106 return 4;
107 }
108
109 len = filesize(fd);
110
111 buf = malloc(len);
112 if (read(fd,buf,len) < len) {
113 fprintf(stderr,"Short read, aborting\n");
114 return 5;
115 }
116
117 /* remove file extension */
118 ext = strchr (array, '.');
119 if (ext != NULL)
120 *ext = '\0';
121 write_cfile (buf, len, cfile, array);
122 fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len);
123
124 close(fd);
125 }
126
127 fclose(cfile);
128 fclose(hfile);
129
130 return 0;
131}
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 Rafaël Carré
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22.text
23
24 #if defined(SANSA_CLIPV2)
25.set RAM_SIZE, 0x100000 /* Use 1MB of SDRAM on v2 firmwares (bigger firmware) */
26#else
27.set RAM_SIZE, 0x50000 /* Use full IRAM on v1 firmwares */
28#endif
29
30/* AS3525 hardware registers */
31.set GPIOA, 0xC80B0000
32.set GPIOB, 0xC80C0000
33.set GPIOC, 0xC80D0000
34.set GPIOD, 0xC80E0000
35.set CGU_PERI, 0xC80F0014
36
37
38/* Vectors */
39
40 ldr pc, =start /* reset vector */
41 /* next vectors are unused */
42 .word 0
43 .word 0
44 .word 0
45 .word 0
46 .word 0
47 .word 0
48 .word 0
49
50/* These values are filled in by mkamsboot - don't move them from offset 0x20 */
51
52uclunpack_end: .word 0 /* End of the ucl_unpack function */
53uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */
54
55ucl_of_end: .word 0 /* End of the ucl-compressed OF image */
56ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */
57
58ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */
59ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */
60
61
62start:
63 /* First copy the UCL unpack function to the end of RAM */
64 ldr r0, uclunpack_end /* Source */
65 ldr r1, uclunpack_size /* Source length */
66 sub r2, r0, r1 /* Source start - 1*/
67
68 ldr r3, =(RAM_SIZE-1) /* Destination end */
69
70uclcopy:
71 ldrb r4, [r0], #-1
72 strb r4, [r3], #-1
73 cmp r2, r0
74 bne uclcopy
75
76 add r5, r3, #2 /* r5 is entry point of copy of uclunpack */
77 /* function, plus one (for thumb mode */
78
79 /* enable gpio clock */
80 ldr r0, =CGU_PERI
81 ldr r1, [r0]
82 orr r1, r1, #(1<<16)
83 str r1, [r0]
84
85
86/* TODO : M200V4 */
87#if defined(SANSA_C200V2)
88#define USB_PIN 1
89#elif defined(SANSA_CLIP) || defined(SANSA_CLIPV2)
90#define USB_PIN 6
91#elif defined(SANSA_FUZE) || defined(SANSA_E200V2)
92#define USB_PIN 3
93#endif
94
95#ifdef USB_PIN /* TODO : remove this check when we'll have an USB driver */
96 ldr r0, =GPIOA
97 mov r1, #0
98 str r1, [r0, #0x400]
99 ldr r1, [r0, #(4*(1<<USB_PIN))]
100 cmp r1, #0
101 bne boot_of
102#endif
103
104 /* Here are model specific tests, for dual boot without a computer */
105 /* All models use left button */
106 /* /!\ Right button for c200v2 (left button is unkwown) */
107
108#ifdef SANSA_CLIP
109.set row, (1<<5) /* enable output on C5 */
110.set col, (1<<0) /* read keyscan column B0 */
111
112 ldr r0, =GPIOC
113 mov r1, #row
114 str r1, [r0, #0x400]
115 str r1, [r0, #(4*row)]
116
117 ldr r0, =GPIOB
118 mov r1, #0
119 str r1, [r0, #0x400]
120 ldr r1, [r0, #(4*col)]
121
122 cmp r1, #0
123 bne boot_of
124#elif defined(SANSA_CLIPV2)
125.set row, (1<<4) /* enable output on D4 */
126.set col, (1<<0) /* read keyscan column D0 */
127
128 ldr r0, =GPIOD
129 mov r1, #((1<<5)|(1<<4)|(1<<3)) /* all rows as output */
130 str r1, [r0, #0x400]
131
132 /* all rows high */
133 mov r1, #(1<<3)
134 str r1, [r0, #(4*(1<<3))]
135 mov r1, #(1<<4)
136 str r1, [r0, #(4*(1<<4))]
137 mov r1, #(1<<5)
138 str r1, [r0, #(4*(1<<5))]
139
140 mov r1, #0 /* button row low */
141 str r1, [r0, #(4*row)]
142
143 mov r1, #5 /* small delay */
1441: subs r1, r1, #1
145 bne 1b
146
147 ldr r1, [r0, #(4*col)]
148
149 cmp r1, #0
150 beq boot_of
151#elif defined(SANSA_E200V2) || defined(SANSA_FUZE)
152 ldr r0, =GPIOC
153 mov r1, #0
154 str r1, [r0, #0x400]
155 ldr r1, [r0, #0x20] /* read pin C3 */
156
157 cmp r1, #0 /* C3 = #0 means button pressed */
158 beq boot_of
159#elif defined(SANSA_C200V2)
160 /* check for RIGHT on C6, should changed to LEFT as soon as it
161 * known in which pin that is in order for consistency */
162 ldr r0, =GPIOC
163 mov r1, #0
164 str r1, [r0, #0x400] /* set pin to output */
165
166 ldr r1, [r0, #256] /* 1<<(6+2) */
167 cmp r1, #0 /* C6 low means button pressed */
168 beq boot_of
169#elif defined(SANSA_M200V4)
170.set row, (1<<5) /* enable output on A5 */
171.set col, (1<<0) /* read keyscan column A0 */
172
173 ldr r0, =GPIOA
174 mov r1, #row
175 str r1, [r0, #0x400]
176 str r1, [r0, #(4*row)]
177
178 ldr r2, [r0, #(4*col)]
179
180 /* check value read (1 means button pressed) */
181 cmp r2, #0
182 bne boot_of
183#else
184 #error No target-specific key check defined!
185#endif
186
187
188 /* The dualboot button was not held, so we boot rockbox */
189 ldr r0, ucl_rb_end /* Address of compressed image */
190 ldr r1, ucl_rb_size /* Compressed size */
191 b decompress
192
193boot_of:
194 ldr r0, ucl_of_end /* Address of compressed image */
195 ldr r1, ucl_of_size /* Compressed size */
196
197
198decompress:
199 /* At this point: */
200 /* r5 = entry point (plus one for thumb) of uclunpack function */
201 /* r3 = destination_end for copy of UCL image */
202 /* r0 = source_end for UCL image to copy */
203 /* r1 = size of UCL image to copy */
204
205 sub r4, r3, r1 /* r4 := destination_start - 1 */
206
207fw_copy:
208 ldrb r2, [r0], #-1
209 strb r2, [r3], #-1
210 cmp r3, r4 /* Stop when we reached dest_start-1 */
211 bne fw_copy
212
213 /* Call the ucl decompress function, which will branch to 0x0 */
214 /* on completion */
215 add r0, r3, #1 /* r0 := Start of compressed image */
216 /* r1 already contains compressed size */
217 mov r2, #0 /* r2 := Destination for unpacking */
218 bx r5 /* Branch to uclunpack, switching to thumb */
219
220 /* 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:
191/* 191/*
192vi:ts=8:et:nowrap 192vi:ts=8:et:nowrap
193 */ 193 */
194
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 @@
1/*
2
3extract_fw.c - extract the main firmware image from a Sansa V2 (AMS) firmware
4 file
5
6Copyright (C) Dave Chapman 2008
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
21
22*/
23
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <stdint.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <string.h>
33
34
35/* Win32 compatibility */
36#ifndef O_BINARY
37#define O_BINARY 0
38#endif
39
40
41static off_t filesize(int fd) {
42 struct stat buf;
43
44 if (fstat(fd,&buf) < 0) {
45 perror("[ERR] Checking filesize of input file");
46 return -1;
47 } else {
48 return(buf.st_size);
49 }
50}
51
52static uint32_t get_uint32le(unsigned char* p)
53{
54 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
55}
56
57void usage(void)
58{
59 printf("Usage: extract_fw <firmware file> <output file>\n");
60
61 exit(1);
62}
63
64int main(int argc, char* argv[])
65{
66 char *infile, *outfile;
67 int fdin, fdout;
68 off_t len;
69 uint32_t n;
70 unsigned char* buf;
71 uint32_t firmware_size;
72
73 if(argc != 3) {
74 usage();
75 }
76
77 infile = argv[1];
78 outfile = argv[2];
79
80 /* Open the firmware file */
81 fdin = open(infile,O_RDONLY|O_BINARY);
82
83 if (fdin < 0) {
84 fprintf(stderr,"[ERR] Could not open %s for reading\n",infile);
85 return 1;
86 }
87
88 if ((len = filesize(fdin)) < 0)
89 return 1;
90
91 /* We will need no more memory than the total size plus the bootloader size
92 padded to a boundary */
93 if ((buf = malloc(len)) == NULL) {
94 fprintf(stderr,"[ERR] Could not allocate buffer for input file (%d bytes)\n",(int)len);
95 return 1;
96 }
97
98 n = read(fdin, buf, len);
99
100 if (n != (uint32_t)len) {
101 fprintf(stderr,"[ERR] Could not read firmware file\n");
102 return 1;
103 }
104
105 close(fdin);
106
107 /* Get the firmware size */
108 firmware_size = get_uint32le(&buf[0x0c]);
109
110 fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666);
111
112 if (fdout < 0) {
113 fprintf(stderr,"[ERR] Could not open %s for writing\n",outfile);
114 return 1;
115 }
116
117 n = write(fdout, buf + 0x400, firmware_size);
118
119 if (n != (uint32_t)firmware_size) {
120 fprintf(stderr,"[ERR] Could not write firmware block\n");
121 return 1;
122 }
123
124 /* Clean up */
125 close(fdout);
126 free(buf);
127
128 return 0;
129}
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] )
123 P( B, C, D, A, 12, 20, 0x8D2A4C8A ); 123 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
124 124
125#undef F 125#undef F
126 126
127#define F(x,y,z) (x ^ y ^ z) 127#define F(x,y,z) (x ^ y ^ z)
128 128
129 P( A, B, C, D, 5, 4, 0xFFFA3942 ); 129 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 @@
24 24
25/* 25/*
26 26
27Insert a Rockbox bootloader into an AMS original firmware file. 27Insert a Rockbox bootloader into a Sansa AMS original firmware file.
28
29Layout of a Sansa AMS original firmware file:
30
31 ---------------------- 0x0
32| HEADER |
33|----------------------| 0x400
34| FIRMWARE BLOCK |
35|----------------------| 0x400 + firmware block size
36| LIBRARIES/DATA |
37 ---------------------- END
28 38
29We replace the main firmware block (bytes 0x400..0x400+firmware_size) 39We replace the main firmware block (bytes 0x400..0x400+firmware_size)
30as follows: 40as follows:
@@ -50,9 +60,12 @@ as follows:
50 60
51This entire block fits into the space previously occupied by the main 61This entire block fits into the space previously occupied by the main
52firmware block - the space saved by compressing the OF image is used 62firmware block - the space saved by compressing the OF image is used
53to store the compressed version of the Rockbox bootloader. The OF 63to store the compressed version of the Rockbox bootloader.
54image is typically about 120KB, which allows us to store a Rockbox 64
55bootloader with an uncompressed size of about 60KB-70KB. 65On version 1 firmwares, the OF image is typically about 120KB, which allows
66us to store a Rockbox bootloader with an uncompressed size of about 60KB-70KB.
67Version 2 firmwares are bigger and are stored in SDRAM (instead of IRAM).
68In both cases, the RAM we are using is mapped at offset 0x0.
56 69
57mkamsboot then corrects the checksums and writes a new legal firmware 70mkamsboot then corrects the checksums and writes a new legal firmware
58file which can be installed on the device. 71file which can be installed on the device.
@@ -65,7 +78,7 @@ end of RAM.
65 78
66Then, depending on the detection of the dual-boot keypress, either the 79Then, depending on the detection of the dual-boot keypress, either the
67OF image or the Rockbox image is copied to the end of RAM (just before 80OF image or the Rockbox image is copied to the end of RAM (just before
68the ucl unpack function) and uncompress it to the start of RAM. 81the ucl unpack function) and uncompressed to the start of RAM.
69 82
70Finally, the ucl unpack function branches to address 0x0, passing 83Finally, the ucl unpack function branches to address 0x0, passing
71execution to the uncompressed firmware. 84execution to the uncompressed firmware.
@@ -73,7 +86,6 @@ execution to the uncompressed firmware.
73 86
74*/ 87*/
75 88
76
77#include <stdio.h> 89#include <stdio.h>
78#include <stdlib.h> 90#include <stdlib.h>
79#include <stdint.h> 91#include <stdint.h>
@@ -85,27 +97,22 @@ execution to the uncompressed firmware.
85 97
86#include <ucl/ucl.h> 98#include <ucl/ucl.h>
87 99
88/* Headers for ARM code binaries */ 100#include "mkamsboot.h"
89#include "nrv2e_d8.h" 101
90#include "md5.h" 102#include "md5.h"
91 103
92#include "dualboot_clip.h" 104/* Header for ARM code binaries */
93#include "dualboot_e200v2.h" 105#include "dualboot.h"
94#include "dualboot_fuze.h"
95#include "dualboot_m200v4.h"
96#include "dualboot_c200v2.h"
97 106
98/* Win32 compatibility */ 107/* Win32 compatibility */
99#ifndef O_BINARY 108#ifndef O_BINARY
100#define O_BINARY 0 109#define O_BINARY 0
101#endif 110#endif
102 111
103#ifndef VERSION 112#define VERSION "1.0"
104#define VERSION "0.1"
105#endif
106 113
107enum 114/* Supported models */
108{ 115enum {
109 MODEL_UNKNOWN = -1, 116 MODEL_UNKNOWN = -1,
110 MODEL_FUZE = 0, 117 MODEL_FUZE = 0,
111 MODEL_CLIP, 118 MODEL_CLIP,
@@ -115,31 +122,31 @@ enum
115 MODEL_C200V2, 122 MODEL_C200V2,
116}; 123};
117 124
118static const char* model_names[] = 125/* Descriptive name of these models */
119{ 126static const char* model_names[] = {
120 "Fuze", 127 "Fuze",
121 "Clip", 128 "Clip",
122 "Clip V2", 129 "Clip v2",
123 "e200 v2", 130 "e200 v2",
124 "m200 v4", 131 "m200 v4",
125 "c200 v2" 132 "c200 v2"
126}; 133};
127 134
128static const unsigned char* bootloaders[] = 135/* Dualboot functions for these models */
129{ 136static const unsigned char* bootloaders[] = {
130 dualboot_fuze, 137 dualboot_fuze,
131 dualboot_clip, 138 dualboot_clip,
132 NULL, 139 dualboot_clipv2,
133 dualboot_e200v2, 140 dualboot_e200v2,
134 dualboot_m200v4, 141 dualboot_m200v4,
135 dualboot_c200v2, 142 dualboot_c200v2,
136}; 143};
137 144
138static const int bootloader_sizes[] = 145/* Size of dualboot functions for these models */
139{ 146static const int bootloader_sizes[] = {
140 sizeof(dualboot_fuze), 147 sizeof(dualboot_fuze),
141 sizeof(dualboot_clip), 148 sizeof(dualboot_clip),
142 0, 149 sizeof(dualboot_clipv2),
143 sizeof(dualboot_e200v2), 150 sizeof(dualboot_e200v2),
144 sizeof(dualboot_m200v4), 151 sizeof(dualboot_m200v4),
145 sizeof(dualboot_c200v2), 152 sizeof(dualboot_c200v2),
@@ -147,11 +154,10 @@ static const int bootloader_sizes[] =
147 154
148/* Model names used in the Rockbox header in ".sansa" files - these match the 155/* Model names used in the Rockbox header in ".sansa" files - these match the
149 -add parameter to the "scramble" tool */ 156 -add parameter to the "scramble" tool */
150static const char* rb_model_names[] = 157static const char* rb_model_names[] = {
151{
152 "fuze", 158 "fuze",
153 "clip", 159 "clip",
154 NULL, 160 "clv2",
155 "e2v2", 161 "e2v2",
156 "m2v4", 162 "m2v4",
157 "c2v2", 163 "c2v2",
@@ -159,11 +165,10 @@ static const char* rb_model_names[] =
159 165
160/* Model numbers used to initialise the checksum in the Rockbox header in 166/* Model numbers used to initialise the checksum in the Rockbox header in
161 ".sansa" files - these are the same as MODEL_NUMBER in config-target.h */ 167 ".sansa" files - these are the same as MODEL_NUMBER in config-target.h */
162static const int rb_model_num[] = 168static const int rb_model_num[] = {
163{
164 43, 169 43,
165 40, 170 40,
166 0, 171 60,
167 41, 172 41,
168 42, 173 42,
169 44 174 44
@@ -172,7 +177,7 @@ static const int rb_model_num[] =
172struct md5sums { 177struct md5sums {
173 int model; 178 int model;
174 char *version; 179 char *version;
175 int fw_version; 180 int fw_version; /* version 2 is used in Clipv2 and Fuzev2 firmwares */
176 char *md5; 181 char *md5;
177}; 182};
178 183
@@ -181,27 +186,32 @@ struct md5sums {
181static struct md5sums sansasums[] = { 186static struct md5sums sansasums[] = {
182 /* NOTE: Different regional versions of the firmware normally only 187 /* NOTE: Different regional versions of the firmware normally only
183 differ in the filename - the md5sums are identical */ 188 differ in the filename - the md5sums are identical */
184 { MODEL_E200V2, "3.01.11", 1, "e622ca8cb6df423f54b8b39628a1f0a3" }, 189
185 { MODEL_E200V2, "3.01.14", 1, "2c1d0383fc3584b2cc83ba8cc2243af6" }, 190 /* model version fw_version md5 */
186 { MODEL_E200V2, "3.01.16", 1, "12563ad71b25a1034cf2092d1e0218c4" }, 191 { MODEL_E200V2, "3.01.11", 1, "e622ca8cb6df423f54b8b39628a1f0a3" },
187 192 { MODEL_E200V2, "3.01.14", 1, "2c1d0383fc3584b2cc83ba8cc2243af6" },
188 { MODEL_FUZE, "1.01.11", 1, "cac8ffa03c599330ac02c4d41de66166" }, 193 { MODEL_E200V2, "3.01.16", 1, "12563ad71b25a1034cf2092d1e0218c4" },
189 { MODEL_FUZE, "1.01.15", 1, "df0e2c1612727f722c19a3c764cff7f2" }, 194
190 { MODEL_FUZE, "1.01.22", 1, "5aff5486fe8dd64239cc71eac470af98" }, 195 { MODEL_FUZE, "1.01.11", 1, "cac8ffa03c599330ac02c4d41de66166" },
191 { MODEL_FUZE, "1.02.26", 1, "7c632c479461c48c8833baed74eb5e4f" }, 196 { MODEL_FUZE, "1.01.15", 1, "df0e2c1612727f722c19a3c764cff7f2" },
192 197 { MODEL_FUZE, "1.01.22", 1, "5aff5486fe8dd64239cc71eac470af98" },
193 { MODEL_C200V2, "3.02.05", 1, "b6378ebd720b0ade3fad4dc7ab61c1a5" }, 198 { MODEL_FUZE, "1.02.26", 1, "7c632c479461c48c8833baed74eb5e4f" },
194 199
195 { MODEL_M200V4, "4.00.45", 1, "82e3194310d1514e3bbcd06e84c4add3" }, 200 { MODEL_C200V2, "3.02.05", 1, "b6378ebd720b0ade3fad4dc7ab61c1a5" },
196 { MODEL_M200V4, "4.01.08-A", 1, "fc9dd6116001b3e6a150b898f1b091f0" }, 201
197 { MODEL_M200V4, "4.01.08-E", 1, "d3fb7d8ec8624ee65bc99f8dab0e2369" }, 202 { MODEL_M200V4, "4.00.45", 1, "82e3194310d1514e3bbcd06e84c4add3" },
198 203 { MODEL_M200V4, "4.01.08-A", 1, "fc9dd6116001b3e6a150b898f1b091f0" },
199 { MODEL_CLIP, "1.01.17", 1, "12caad785d506219d73f538772afd99e" }, 204 { MODEL_M200V4, "4.01.08-E", 1, "d3fb7d8ec8624ee65bc99f8dab0e2369" },
200 { MODEL_CLIP, "1.01.18", 1, "d720b266bd5afa38a198986ef0508a45" }, 205
201 { MODEL_CLIP, "1.01.20", 1, "236d8f75189f468462c03f6d292cf2ac" }, 206 { MODEL_CLIP, "1.01.17", 1, "12caad785d506219d73f538772afd99e" },
202 { MODEL_CLIP, "1.01.29", 1, "c12711342169c66e209540cd1f27cd26" }, 207 { MODEL_CLIP, "1.01.18", 1, "d720b266bd5afa38a198986ef0508a45" },
203 { MODEL_CLIP, "1.01.30", 1, "f2974d47c536549c9d8259170f1dbe4d" }, 208 { MODEL_CLIP, "1.01.20", 1, "236d8f75189f468462c03f6d292cf2ac" },
204 { MODEL_CLIP, "1.01.32", 1, "d835d12342500732ffb9c4ee54abec15" }, 209 { MODEL_CLIP, "1.01.29", 1, "c12711342169c66e209540cd1f27cd26" },
210 { MODEL_CLIP, "1.01.30", 1, "f2974d47c536549c9d8259170f1dbe4d" },
211 { MODEL_CLIP, "1.01.32", 1, "d835d12342500732ffb9c4ee54abec15" },
212
213 { MODEL_CLIPV2, "2.01.16", 2, "c57fb3fcbe07c2c9b360f060938f80cb" },
214 { MODEL_CLIPV2, "2.01.32", 2, "0ad3723e52022509089d938d0fbbf8c5" }
205}; 215};
206 216
207#define NUM_MD5S (sizeof(sansasums)/sizeof(sansasums[0])) 217#define NUM_MD5S (sizeof(sansasums)/sizeof(sansasums[0]))
@@ -209,7 +219,7 @@ static struct md5sums sansasums[] = {
209static off_t filesize(int fd) { 219static off_t filesize(int fd) {
210 struct stat buf; 220 struct stat buf;
211 221
212 if (fstat(fd,&buf) < 0) { 222 if (fstat(fd, &buf) < 0) {
213 perror("[ERR] Checking filesize of input file"); 223 perror("[ERR] Checking filesize of input file");
214 return -1; 224 return -1;
215 } else { 225 } else {
@@ -217,30 +227,26 @@ static off_t filesize(int fd) {
217 } 227 }
218} 228}
219 229
220static uint32_t get_uint32le(unsigned char* p) 230static uint32_t get_uint32le(unsigned char* p) {
221{
222 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 231 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
223} 232}
224 233
225static uint32_t get_uint32be(unsigned char* p) 234static uint32_t get_uint32be(unsigned char* p) {
226{
227 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 235 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
228} 236}
229 237
230static void put_uint32le(unsigned char* p, uint32_t x) 238static void put_uint32le(unsigned char* p, uint32_t x) {
231{
232 p[0] = x & 0xff; 239 p[0] = x & 0xff;
233 p[1] = (x >> 8) & 0xff; 240 p[1] = (x >> 8) & 0xff;
234 p[2] = (x >> 16) & 0xff; 241 p[2] = (x >> 16) & 0xff;
235 p[3] = (x >> 24) & 0xff; 242 p[3] = (x >> 24) & 0xff;
236} 243}
237 244
238void calc_MD5(unsigned char* buf, int len, char *md5str) 245void calc_MD5(unsigned char* buf, int len, char *md5str) {
239{
240 int i; 246 int i;
241 md5_context ctx; 247 md5_context ctx;
242 unsigned char md5sum[16]; 248 unsigned char md5sum[16];
243 249
244 md5_starts(&ctx); 250 md5_starts(&ctx);
245 md5_update(&ctx, buf, len); 251 md5_update(&ctx, buf, len);
246 md5_finish(&ctx, md5sum); 252 md5_finish(&ctx, md5sum);
@@ -249,9 +255,8 @@ void calc_MD5(unsigned char* buf, int len, char *md5str)
249 sprintf(md5str + 2*i, "%02x", md5sum[i]); 255 sprintf(md5str + 2*i, "%02x", md5sum[i]);
250} 256}
251 257
252 258/* Calculate a simple checksum used in Sansa Original Firmwares */
253static uint32_t calc_checksum(unsigned char* buf, uint32_t n) 259static uint32_t calc_checksum(unsigned char* buf, uint32_t n) {
254{
255 uint32_t sum = 0; 260 uint32_t sum = 0;
256 uint32_t i; 261 uint32_t i;
257 262
@@ -261,10 +266,8 @@ static uint32_t calc_checksum(unsigned char* buf, uint32_t n)
261 return sum; 266 return sum;
262} 267}
263 268
264static int get_model(int model_id) 269static int get_model(int model_id) {
265{ 270 switch(model_id) {
266 switch(model_id)
267 {
268 case 0x1e: 271 case 0x1e:
269 return MODEL_FUZE; 272 return MODEL_FUZE;
270 case 0x22: 273 case 0x22:
@@ -282,9 +285,8 @@ static int get_model(int model_id)
282 return MODEL_UNKNOWN; 285 return MODEL_UNKNOWN;
283} 286}
284 287
285 288/* Compress using nrv2e algorithm : Thumb decompressor fits in 168 bytes ! */
286static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize) 289static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize) {
287{
288 int maxsize; 290 int maxsize;
289 unsigned char* outbuf; 291 unsigned char* outbuf;
290 int r; 292 int r;
@@ -295,10 +297,9 @@ static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
295 /* Allocate some memory for the output buffer */ 297 /* Allocate some memory for the output buffer */
296 outbuf = malloc(maxsize); 298 outbuf = malloc(maxsize);
297 299
298 if (outbuf == NULL) { 300 if (outbuf == NULL)
299 return NULL; 301 return NULL;
300 } 302
301
302 r = ucl_nrv2e_99_compress( 303 r = ucl_nrv2e_99_compress(
303 (const ucl_bytep) inbuf, 304 (const ucl_bytep) inbuf,
304 (ucl_uint) insize, 305 (ucl_uint) insize,
@@ -306,8 +307,7 @@ static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
306 (ucl_uintp) outsize, 307 (ucl_uintp) outsize,
307 0, 10, NULL, NULL); 308 0, 10, NULL, NULL);
308 309
309 if (r != UCL_E_OK || *outsize > maxsize) 310 if (r != UCL_E_OK || *outsize > maxsize) {
310 {
311 /* this should NEVER happen, and implies memory corruption */ 311 /* this should NEVER happen, and implies memory corruption */
312 fprintf(stderr, "internal error - compression failed: %d\n", r); 312 fprintf(stderr, "internal error - compression failed: %d\n", r);
313 free(outbuf); 313 free(outbuf);
@@ -317,42 +317,105 @@ static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize)
317 return outbuf; 317 return outbuf;
318} 318}
319 319
320static unsigned char* load_file(char* filename, off_t* bufsize) 320#define ERROR(format, ...) \
321{ 321 do { \
322 snprintf(errstr, errstrsize, format, __VA_ARGS__); \
323 goto error; \
324 } while(0)
325
326/* Loads a Sansa AMS Original Firmware file into memory */
327unsigned char* load_of_file(
328 char* filename, off_t* bufsize, char* md5sum, int* model,
329 int* fw_version, int* firmware_size, unsigned char** of_packed,
330 int* of_packedsize, char* errstr, int errstrsize
331) {
322 int fd; 332 int fd;
323 unsigned char* buf; 333 unsigned char* buf =NULL;
324 off_t n; 334 off_t n;
335 unsigned int i=0;
336 uint32_t checksum;
337 int model_id;
338 unsigned int last_word;
325 339
326 fd = open(filename, O_RDONLY|O_BINARY); 340 fd = open(filename, O_RDONLY|O_BINARY);
327 if (fd < 0) 341 if (fd < 0)
328 { 342 ERROR("[ERR] Could not open %s for reading\n", filename);
329 fprintf(stderr,"[ERR] Could not open %s for reading\n",filename);
330 return NULL;
331 }
332 343
333 *bufsize = filesize(fd); 344 *bufsize = filesize(fd);
334 345
335 buf = malloc(*bufsize); 346 buf = malloc(*bufsize);
336 if (buf == NULL) { 347 if (buf == NULL)
337 fprintf(stderr,"[ERR] Could not allocate memory for %s\n",filename); 348 ERROR("[ERR] Could not allocate memory for %s\n", filename);
338 return NULL;
339 }
340 349
341 n = read(fd, buf, *bufsize); 350 n = read(fd, buf, *bufsize);
342 351
343 if (n != *bufsize) { 352 if (n != *bufsize)
344 fprintf(stderr,"[ERR] Could not read file %s\n",filename); 353 ERROR("[ERR] Could not read file %s\n", filename);
345 return NULL; 354
355 /* check the file */
356
357 /* Calculate MD5 checksum of OF */
358 calc_MD5(buf, *bufsize, md5sum);
359
360 while ((i < NUM_MD5S) && (strcmp(sansasums[i].md5, md5sum) != 0))
361 i++;
362
363 if (i < NUM_MD5S) {
364 *model = sansasums[i].model;
365 *fw_version = sansasums[i].fw_version;
366 } else {
367 fprintf(stderr, "[WARN] ****** Original firmware unknown ******\n");
368 if (get_uint32le(&buf[0x204])==0x0000f000) {
369 *fw_version = 2;
370 model_id = buf[0x219];
371 } else {
372 *fw_version = 1;
373 model_id = buf[0x215];
374 }
375
376 *model = get_model(model_id);
377
378 if (*model == MODEL_UNKNOWN)
379 ERROR("[ERR] Unknown firmware - model id 0x%02x\n", model_id);
346 } 380 }
347 381
382 /* TODO: Do some more sanity checks on the OF image. Some images (like
383 m200v4) dont have a checksum at the end, only padding (0xdeadbeef). */
384 last_word = *bufsize - 4;
385 checksum = get_uint32le(buf + last_word);
386 if (checksum != 0xefbeadde && checksum != calc_checksum(buf, last_word))
387 ERROR("%s", "[ERR] Whole file checksum failed\n");
388
389 if (bootloaders[*model] == NULL)
390 ERROR("[ERR] Unsupported model - \"%s\"\n", model_names[*model]);
391
392
393 /* Get the firmware size */
394 if (*fw_version == 1)
395 *firmware_size = get_uint32le(&buf[0x0c]);
396 else /* fw_version == 2 */
397 *firmware_size = get_uint32le(&buf[0x10]);
398
399 /* Compress the original firmware image */
400 *of_packed = uclpack(buf + 0x400, *firmware_size, of_packedsize);
401 if (*of_packed == NULL)
402 ERROR("[ERR] Could not compress %s\n", filename);
403
348 return buf; 404 return buf;
349}
350 405
406error:
407 free(buf);
408 return NULL;
409}
351 410
352static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsize) 411/* Loads a rockbox bootloader file into memory */
353{ 412unsigned char* load_rockbox_file(
413 char* filename, int model, int* bufsize, int* rb_packedsize,
414 char* errstr, int errstrsize
415) {
354 int fd; 416 int fd;
355 unsigned char* buf; 417 unsigned char* buf = NULL;
418 unsigned char* packed = NULL;
356 unsigned char header[8]; 419 unsigned char header[8];
357 uint32_t sum; 420 uint32_t sum;
358 off_t n; 421 off_t n;
@@ -360,39 +423,28 @@ static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsiz
360 423
361 fd = open(filename, O_RDONLY|O_BINARY); 424 fd = open(filename, O_RDONLY|O_BINARY);
362 if (fd < 0) 425 if (fd < 0)
363 { 426 ERROR("[ERR] Could not open %s for reading\n", filename);
364 fprintf(stderr,"[ERR] Could not open %s for reading\n",filename);
365 return NULL;
366 }
367 427
368 /* Read Rockbox header */ 428 /* Read Rockbox header */
369 n = read(fd, header, sizeof(header)); 429 n = read(fd, header, sizeof(header));
370 if (n != sizeof(header)) { 430 if (n != sizeof(header))
371 fprintf(stderr,"[ERR] Could not read file %s\n",filename); 431 ERROR("[ERR] Could not read file %s\n", filename);
372 return NULL;
373 }
374 432
375 /* Check for correct model string */ 433 /* Check for correct model string */
376 if (memcmp(rb_model_names[model],header + 4,4)!=0) { 434 if (memcmp(rb_model_names[model], header + 4, 4)!=0)
377 fprintf(stderr,"[ERR] Model name \"%s\" not found in %s\n", 435 ERROR("[ERR] Model name \"%s\" not found in %s\n",
378 rb_model_names[model],filename); 436 rb_model_names[model], filename);
379 return NULL;
380 }
381 437
382 *bufsize = filesize(fd) - sizeof(header); 438 *bufsize = filesize(fd) - sizeof(header);
383 439
384 buf = malloc(*bufsize); 440 buf = malloc(*bufsize);
385 if (buf == NULL) { 441 if (buf == NULL)
386 fprintf(stderr,"[ERR] Could not allocate memory for %s\n",filename); 442 ERROR("[ERR] Could not allocate memory for %s\n", filename);
387 return NULL;
388 }
389 443
390 n = read(fd, buf, *bufsize); 444 n = read(fd, buf, *bufsize);
391 445
392 if (n != *bufsize) { 446 if (n != *bufsize)
393 fprintf(stderr,"[ERR] Could not read file %s\n",filename); 447 ERROR("[ERR] Could not read file %s\n", filename);
394 return NULL;
395 }
396 448
397 /* Check checksum */ 449 /* Check checksum */
398 sum = rb_model_num[model]; 450 sum = rb_model_num[model];
@@ -401,176 +453,36 @@ static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsiz
401 sum += buf[i]; 453 sum += buf[i];
402 } 454 }
403 455
404 if (sum != get_uint32be(header)) { 456 if (sum != get_uint32be(header))
405 fprintf(stderr,"[ERR] Checksum mismatch in %s\n",filename); 457 ERROR("[ERR] Checksum mismatch in %s\n", filename);
406 return NULL;
407 }
408 return buf;
409}
410
411
412int main(int argc, char* argv[])
413{
414 char *infile, *bootfile, *outfile;
415 int fdout;
416 off_t len;
417 uint32_t n;
418 unsigned char* buf;
419 int firmware_size;
420 off_t bootloader_size;
421 uint32_t sum,filesum;
422 uint8_t model_id;
423 int model;
424 uint32_t i;
425 unsigned char* of_packed;
426 int of_packedsize;
427 unsigned char* rb_unpacked;
428 unsigned char* rb_packed;
429 int rb_packedsize;
430 int fw_version;
431 int totalsize;
432 unsigned char* p;
433 uint32_t checksum;
434 char md5sum[33]; /* 32 hex digits, plus terminating zero */
435
436 fprintf(stderr,"mkamsboot v" VERSION " - (C) Dave Chapman and Rafaël Carré 2008\n");
437 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
438 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
439
440 if(argc != 4) {
441 printf("Usage: mkamsboot <firmware file> <boot file> <output file>\n\n");
442 return 1;
443 }
444
445 infile = argv[1];
446 bootfile = argv[2];
447 outfile = argv[3];
448
449 /* Load original firmware file */
450 buf = load_file(infile, &len);
451
452 if (buf == NULL) {
453 fprintf(stderr,"[ERR] Could not load %s\n",infile);
454 return 1;
455 }
456
457 /* Calculate MD5 checksum of OF */
458 calc_MD5(buf, len, md5sum);
459 458
460 fprintf(stderr,"[INFO] MD5 sum - %s\n",md5sum); 459 packed = uclpack(buf, *bufsize, rb_packedsize);
460 if(packed == NULL)
461 ERROR("[ERR] Could not compress %s\n", filename);
461 462
462 i = 0; 463 free(buf);
463 while ((i < NUM_MD5S) && (strcmp(sansasums[i].md5, md5sum) != 0)) 464 return packed;
464 i++;
465 465
466 if (i < NUM_MD5S) { 466error:
467 model = sansasums[i].model; 467 free(buf);
468 fw_version = sansasums[i].fw_version; 468 return NULL;
469 fprintf(stderr,"[INFO] Original firmware MD5 checksum match - %s %s\n", 469}
470 model_names[model], sansasums[i].version);
471 } else {
472 if (get_uint32le(&buf[0x204])==0x0000f000) {
473 fw_version = 2;
474 model_id = buf[0x219];
475 } else {
476 fw_version = 1;
477 model_id = buf[0x215];
478 }
479
480 model = get_model(model_id);
481
482#if 0
483 /* if you are a tester this info might help */
484 fprintf(stderr,"[WARN] ****** Original firmware unknown ******\n");
485 if (model == MODEL_UNKNOWN) {
486 fprintf(stderr,"[ERR] Unknown firmware - model id 0x%02x\n",
487 model_id);
488 free(buf);
489 return 1;
490 }
491#else
492 /* else you don't want to brick your player */
493 fprintf(stderr, "[ERR] Original firmware untested - aborting\n");
494 free(buf);
495 return 1;
496#endif
497 }
498
499
500 /* TODO: Do some more sanity checks on the OF image. Some images (like
501 m200v4) dont have a checksum at the end, only padding (0xdeadbeef). */
502 checksum = get_uint32le(buf + len - 4);
503 if (checksum != 0xefbeadde && checksum != calc_checksum(buf, len - 4)) {
504
505 fprintf(stderr,"[ERR] Whole file checksum failed - %s\n",infile);
506 free(buf);
507 return 1;
508 }
509
510 if (bootloaders[model] == NULL) {
511 fprintf(stderr,"[ERR] Unsupported model - \"%s\"\n",model_names[model]);
512 free(buf);
513 return 1;
514 }
515
516 /* Load bootloader file */
517 rb_unpacked = load_rockbox_file(bootfile, model, &bootloader_size);
518 if (rb_unpacked == NULL) {
519 fprintf(stderr,"[ERR] Could not load %s\n",bootfile);
520 free(buf);
521 return 1;
522 }
523
524 printf("[INFO] Patching %s firmware\n",model_names[model]);
525
526 /* Get the firmware size */
527 firmware_size = get_uint32le(&buf[0x0c]);
528
529 /* Compress the original firmware image */
530 of_packed = uclpack(buf + 0x400, firmware_size, &of_packedsize);
531 if (of_packed == NULL) {
532 fprintf(stderr,"[ERR] Could not compress original firmware\n");
533 free(buf);
534 free(rb_unpacked);
535 return 1;
536 }
537
538 rb_packed = uclpack(rb_unpacked, bootloader_size, &rb_packedsize);
539 if (rb_packed == NULL) {
540 fprintf(stderr,"[ERR] Could not compress %s\n",bootfile);
541 free(buf);
542 free(rb_unpacked);
543 free(of_packed);
544 return 1;
545 }
546
547 /* We are finished with the unpacked version of the bootloader */
548 free(rb_unpacked);
549
550 fprintf(stderr,"[INFO] Original firmware size: %d bytes\n",firmware_size);
551 fprintf(stderr,"[INFO] Packed OF size: %d bytes\n",of_packedsize);
552 fprintf(stderr,"[INFO] Bootloader size: %d bytes\n",(int)bootloader_size);
553 fprintf(stderr,"[INFO] Packed bootloader size: %d bytes\n",rb_packedsize);
554 fprintf(stderr,"[INFO] Dual-boot function size: %d bytes\n",bootloader_sizes[model]);
555 fprintf(stderr,"[INFO] UCL unpack function size: %d bytes\n",sizeof(nrv2e_d8));
556
557 totalsize = bootloader_sizes[model] + sizeof(nrv2e_d8) + of_packedsize +
558 rb_packedsize;
559 470
560 fprintf(stderr,"[INFO] Total size of new image: %d bytes\n",totalsize); 471#undef ERROR
561 472
562 if (totalsize > firmware_size) { 473/* Patches a Sansa AMS Original Firmware file */
563 fprintf(stderr,"[ERR] No room to insert bootloader, aborting\n"); 474void patch_firmware(
564 free(buf); 475 int model, int fw_version, int firmware_size, unsigned char* buf,
565 free(rb_unpacked); 476 int len, unsigned char* of_packed, int of_packedsize,
566 free(of_packed); 477 unsigned char* rb_packed, int rb_packedsize
567 return 1; 478) {
568 } 479 unsigned char *p;
480 uint32_t sum, filesum;
481 unsigned int i;
569 482
570 /* Zero the original firmware area - not needed, but helps debugging */ 483 /* Zero the original firmware area - not needed, but helps debugging */
571 memset(buf + 0x400, 0, firmware_size); 484 memset(buf + 0x400, 0, firmware_size);
572 485
573
574 /* Insert dual-boot bootloader at offset 0 */ 486 /* Insert dual-boot bootloader at offset 0 */
575 memcpy(buf + 0x400, bootloaders[model], bootloader_sizes[model]); 487 memcpy(buf + 0x400, bootloaders[model], bootloader_sizes[model]);
576 488
@@ -589,7 +501,7 @@ int main(int argc, char* argv[])
589 p -= rb_packedsize; 501 p -= rb_packedsize;
590 memcpy(p, rb_packed, rb_packedsize); 502 memcpy(p, rb_packed, rb_packedsize);
591 503
592 /* Write the locations of the various images to the variables at the 504 /* Write the locations of the various images to the variables at the
593 start of the dualboot image - we save the location of the last byte 505 start of the dualboot image - we save the location of the last byte
594 in each image, along with the size in bytes */ 506 in each image, along with the size in bytes */
595 507
@@ -602,19 +514,18 @@ int main(int argc, char* argv[])
602 put_uint32le(&buf[0x42c], of_packedsize); 514 put_uint32le(&buf[0x42c], of_packedsize);
603 515
604 /* Compressed Rockbox image */ 516 /* Compressed Rockbox image */
605 put_uint32le(&buf[0x430], firmware_size - sizeof(nrv2e_d8) - of_packedsize - 1); 517 put_uint32le(&buf[0x430], firmware_size - sizeof(nrv2e_d8) - of_packedsize
518 - 1);
606 put_uint32le(&buf[0x434], rb_packedsize); 519 put_uint32le(&buf[0x434], rb_packedsize);
607 520
608 521
609 /* Update the firmware block checksum */ 522 /* Update the firmware block checksum */
610 sum = calc_checksum(buf + 0x400,firmware_size); 523 sum = calc_checksum(buf + 0x400, firmware_size);
611 524
612 if (fw_version == 1) { 525 if (fw_version == 1) {
613 put_uint32le(&buf[0x04], sum); 526 put_uint32le(&buf[0x04], sum);
614 put_uint32le(&buf[0x204], sum); 527 put_uint32le(&buf[0x204], sum);
615 } else { 528 } else {
616 /* TODO: Verify that this is correct for the v2 firmware */
617
618 put_uint32le(&buf[0x08], sum); 529 put_uint32le(&buf[0x08], sum);
619 put_uint32le(&buf[0x208], sum); 530 put_uint32le(&buf[0x208], sum);
620 531
@@ -629,29 +540,130 @@ int main(int argc, char* argv[])
629 filesum += get_uint32le(&buf[i]); 540 filesum += get_uint32le(&buf[i]);
630 541
631 put_uint32le(buf + len - 4, filesum); 542 put_uint32le(buf + len - 4, filesum);
543}
632 544
545/* returns size of new firmware block */
546int total_size(int model, int rb_packedsize, int of_packedsize) {
547 return bootloader_sizes[model] + sizeof(nrv2e_d8) + of_packedsize +
548 rb_packedsize;
549}
550
551#ifndef LIB
552/* standalone executable */
553int main(int argc, char* argv[]) {
554 char *infile, *bootfile, *outfile;
555 int fdout;
556 off_t len;
557 uint32_t n;
558 unsigned char* buf;
559 int firmware_size;
560 int bootloader_size;
561 int model;
562 unsigned char* of_packed;
563 int of_packedsize;
564 unsigned char* rb_packed;
565 int rb_packedsize;
566 int fw_version;
567 int totalsize;
568 char md5sum[33]; /* 32 hex digits, plus terminating zero */
569 char errstr[200];
570
571 fprintf(stderr,
572"mkamsboot v" VERSION " - (C) Dave Chapman and Rafaël Carré 2008\n"
573"This is free software; see the source for copying conditions. There is NO\n"
574"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
575"\n");
576
577 if(argc != 4) {
578 printf("Usage: mkamsboot <firmware file> <boot file> <output file>\n");
579 return 1;
580 }
581
582 infile = argv[1];
583 bootfile = argv[2];
584 outfile = argv[3];
585
586 /* Load original firmware file */
587 buf = load_of_file(infile, &len, md5sum, &model, &fw_version,
588 &firmware_size, &of_packed, &of_packedsize, errstr, sizeof(errstr));
589
590 if (buf == NULL) {
591 fprintf(stderr, "%s", errstr);
592 fprintf(stderr, "[ERR] Could not load %s\n", infile);
593 return 1;
594 }
595
596 fprintf(stderr, "[INFO] Original firmware MD5 checksum match - %s\n",
597 model_names[model]);
598
599
600 /* Load bootloader file */
601 rb_packed = load_rockbox_file(bootfile, model, &bootloader_size,
602 &rb_packedsize, errstr, sizeof(errstr));
603 if (rb_packed == NULL) {
604 fprintf(stderr, "%s", errstr);
605 fprintf(stderr, "[ERR] Could not load %s\n", bootfile);
606 free(buf);
607 free(of_packed);
608 return 1;
609 }
610
611 printf("[INFO] Patching %s firmware\n", model_names[model]);
612
613 fprintf(stderr, "[INFO] Original firmware size: %d bytes\n",
614 firmware_size);
615 fprintf(stderr, "[INFO] Packed OF size: %d bytes\n",
616 of_packedsize);
617 fprintf(stderr, "[INFO] Bootloader size: %d bytes\n",
618 (int)bootloader_size);
619 fprintf(stderr, "[INFO] Packed bootloader size: %d bytes\n",
620 rb_packedsize);
621 fprintf(stderr, "[INFO] Dual-boot function size: %d bytes\n",
622 bootloader_sizes[model]);
623 fprintf(stderr, "[INFO] UCL unpack function size: %d bytes\n",
624 sizeof(nrv2e_d8));
625
626 totalsize = total_size(model, of_packedsize, rb_packedsize);
627
628 fprintf(stderr, "[INFO] Total size of new image: %d bytes\n", totalsize);
629
630 if (totalsize > firmware_size) {
631 fprintf(stderr, "[ERR] No room to insert bootloader, aborting\n");
632 free(buf);
633 free(of_packed);
634 free(rb_packed);
635 return 1;
636 }
637
638 patch_firmware(model, fw_version, firmware_size, buf, len, of_packed,
639 of_packedsize, rb_packed, rb_packedsize);
633 640
634 /* Write the new firmware */ 641 /* Write the new firmware */
635 fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); 642 fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666);
636 643
637 if (fdout < 0) { 644 if (fdout < 0) {
638 fprintf(stderr,"[ERR] Could not open %s for writing\n",outfile); 645 fprintf(stderr, "[ERR] Could not open %s for writing\n", outfile);
646 free(buf);
647 free(of_packed);
648 free(rb_packed);
639 return 1; 649 return 1;
640 } 650 }
641 651
642 n = write(fdout, buf, len); 652 n = write(fdout, buf, len);
643 653
644 if (n != (unsigned)len) { 654 if (n != (unsigned)len) {
645 fprintf(stderr,"[ERR] Could not write firmware file\n"); 655 fprintf(stderr, "[ERR] Could not write firmware file\n");
656 free(buf);
657 free(of_packed);
658 free(rb_packed);
646 return 1; 659 return 1;
647 } 660 }
648 661
649 close(fdout); 662 close(fdout);
650 663 free(buf);
651 fprintf(stderr," *****************************************************************************\n"); 664 free(of_packed);
652 fprintf(stderr," *** THIS CODE IS UNTESTED - DO NOT USE IF YOU CAN NOT RECOVER YOUR DEVICE ***\n"); 665 free(rb_packed);
653 fprintf(stderr," *****************************************************************************\n");
654 666
655 return 0; 667 return 0;
656
657} 668}
669#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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * mkamsboot.h - a tool for merging bootloader code into an Sansa V2
11 * (AMS) firmware file
12 *
13 * Copyright (C) 2008 Dave Chapman
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#ifndef MKAMSBOOT_H
26#define MKAMSBOOT_H
27
28#include <stdint.h>
29#include <sys/types.h>
30
31
32/* load_rockbox_file()
33 *
34 * Loads a rockbox bootloader file into memory
35 *
36 * ARGUMENTS
37 *
38 * filename : bootloader file to load
39 * model : a 4 characters string representing the Sansa model
40 * ("fuze", "clip", "e2v2", "m2v4", or "c2v2")
41 * bootloader_size : set to the uncompressed bootloader size
42 * rb_packed_size : set to the size of compressed bootloader
43 * errstr : provided buffer to store an eventual error
44 * errstrsize : size of provided error buffer
45 *
46 * RETURN VALUE
47 * pointer to allocated memory containing the content of compressed bootloader
48 * or NULL in case of error (errstr will hold a description of the error)
49 */
50
51unsigned char* load_rockbox_file(
52 char* filename, int model, int* bootloader_size, int* rb_packedsize,
53 char* errstr, int errstrsize);
54
55
56/* load_of_file()
57 *
58 * Loads a Sansa AMS Original Firmware file into memory
59 *
60 * ARGUMENTS
61 *
62 * filename : firmware file to load
63 * bufsize : set to firmware file size
64 * md5sum : set to file md5sum, must be at least 33 bytes long
65 * model : set to firmware model (MODEL_XXX)
66 * fw_version : set to firmware format version (1 or 2)
67 * firmware_size : set to firmware block's size
68 * of_packed : pointer to allocated memory containing the compressed
69 * original firmware block
70 * of_packedsize : size of compressed original firmware block
71 * errstr : provided buffer to store an eventual error
72 * errstrsize : size of provided error buffer
73 *
74 * RETURN VALUE
75 * pointer to allocated memory containing the content of Original Firmware
76 * or NULL in case of error (errstr will hold a description of the error)
77 */
78
79unsigned char* load_of_file(
80 char* filename, off_t* bufsize, char* md5sum, int* model,
81 int* fw_version, int* firmware_size, unsigned char** of_packed,
82 int* of_packedsize, char* errstr, int errstrsize);
83
84
85/* patch_firmware()
86 *
87 * Patches a Sansa AMS Original Firmware file
88 *
89 * ARGUMENTS
90 *
91 * model : firmware model (MODEL_XXX)
92 * fw_version : firmware format version (1 or 2)
93 * firmware_size : size of uncompressed original firmware block
94 * buf : pointer to original firmware file
95 * len : size of original firmware file
96 * of_packed : pointer to compressed original firmware block
97 * of_packedsize : size of compressed original firmware block
98 * rb_packed : pointer to compressed rockbox bootloader
99 * rb_packed_size : size of compressed rockbox bootloader
100 */
101
102void patch_firmware(
103 int model, int fw_version, int firmware_size, unsigned char* buf,
104 int len, unsigned char* of_packed, int of_packedsize,
105 unsigned char* rb_packed, int rb_packedsize);
106
107
108/* total_size()
109 *
110 * Calculates the size of the new firmware block
111 *
112 * ARGUMENTS
113 *
114 * model : firmware model (MODEL_XXX)
115 * rb_packed_size : size of compressed rockbox bootloader
116 * of_packedsize : size of compressed original firmware block
117 *
118 * RETURN VALUE
119 * Size of new firmware block
120*/
121
122int total_size(int model, int rb_packedsize, int of_packedsize);
123
124#endif