diff options
Diffstat (limited to 'rbutil')
-rw-r--r-- | rbutil/mkamsboot/Makefile | 106 | ||||
-rw-r--r-- | rbutil/mkamsboot/README | 61 | ||||
-rw-r--r-- | rbutil/mkamsboot/bin2c.c | 134 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot.S | 184 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot.c | 118 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot.h | 9 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot/Makefile | 54 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot/bin2c.c | 131 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot/dualboot.S | 220 | ||||
-rw-r--r-- | rbutil/mkamsboot/dualboot/nrv2e_d8.S (renamed from rbutil/mkamsboot/nrv2e_d8.S) | 1 | ||||
-rw-r--r-- | rbutil/mkamsboot/extract_fw.c | 129 | ||||
-rw-r--r-- | rbutil/mkamsboot/md5.c | 2 | ||||
-rw-r--r-- | rbutil/mkamsboot/mkamsboot.c | 598 | ||||
-rw-r--r-- | rbutil/mkamsboot/mkamsboot.h | 124 |
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 @@ | |||
1 | CC=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 |
4 | CFLAGS=-I../../tools/ucl/include | 2 | CFLAGS=-I../../tools/ucl/include -Wall |
5 | LIBUCL=../../tools/ucl/src/libucl.a | 3 | LIBUCL=../../tools/ucl/src/libucl.a |
6 | 4 | ||
7 | # Edit the following variables (plus copy/paste another set of rules) when | 5 | ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN) |
8 | # adding a new target. mkamsboot.c also needs to be edited to refer to these | 6 | OUTPUT=mkamsboot.exe |
9 | # new images. | 7 | CFLAGS+=-mno-cygwin |
10 | 8 | else | |
11 | BOOTIMAGES = dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o | 9 | ifeq ($(findstring MINGW,$(shell uname)),MINGW) |
12 | BOOTHEADERS = dualboot_clip.h dualboot_e200v2.h dualboot_c200v2.h dualboot_m200v4.h dualboot_fuze.h | 10 | OUTPUT=mkamsboot.exe |
13 | 11 | else | |
14 | CLIPFILES = dualboot_clip.arm-o dualboot_clip.o dualboot_clip.c dualboot_clip.h | 12 | ifeq ($(findstring mingw,$(CC)),mingw) |
15 | 13 | OUTPUT=mkamsboot.exe | |
16 | E200V2FILES = dualboot_e200v2.arm-o dualboot_e200v2.o dualboot_e200v2.c \ | 14 | else |
17 | dualboot_e200v2.h | 15 | OUTPUT=mkamsboot |
18 | 16 | endif | |
19 | M200V4FILES = dualboot_m200v4.arm-o dualboot_m200v4.o dualboot_m200v4.arm-bin \ | 17 | endif |
20 | dualboot_m200v4.c dualboot_m200v4.h | 18 | endif |
21 | 19 | ||
22 | C200V2FILES = dualboot_c200v2.arm-o dualboot_c200v2.o dualboot_c200v2.c \ | 20 | CC?= gcc |
23 | dualboot_c200v2.h | 21 | |
24 | 22 | all: $(OUTPUT) | |
25 | FUZEFILES = dualboot_fuze.arm-o dualboot_fuze.o dualboot_fuze.c dualboot_fuze.h | ||
26 | |||
27 | all: mkamsboot | ||
28 | |||
29 | # Dualboot bootloaders | ||
30 | |||
31 | dualboot_clip.arm-o: dualboot.S | ||
32 | arm-elf-gcc -DSANSA_CLIP -c -o dualboot_clip.arm-o dualboot.S | ||
33 | |||
34 | dualboot_fuze.arm-o: dualboot.S | ||
35 | arm-elf-gcc -DSANSA_FUZE -c -o dualboot_fuze.arm-o dualboot.S | ||
36 | |||
37 | dualboot_e200v2.arm-o: dualboot.S | ||
38 | arm-elf-gcc -DSANSA_E200V2 -c -o dualboot_e200v2.arm-o dualboot.S | ||
39 | |||
40 | dualboot_m200v4.arm-o: dualboot.S | ||
41 | arm-elf-gcc -DSANSA_M200V4 -c -o dualboot_m200v4.arm-o dualboot.S | ||
42 | |||
43 | dualboot_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 | ||
47 | nrv2e_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 | ||
28 | dualboot.o: dualboot.c | ||
29 | $(CC) $(CFLAGS) -c -o dualboot.o dualboot.c | ||
30 | |||
55 | md5.o: md5.c md5.h | 31 | md5.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 | ||
58 | mkamsboot.o: mkamsboot.c $(BOOTHEADERS) nrv2e_d8.h md5.h | 34 | mkamsboot.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 | ||
61 | mkamsboot: 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 | 40 | libmkamsboot.o: mkamsboot.c dualboot.h md5.h |
81 | %.o: %.S | 41 | $(CC) $(CFLAGS) -DLIB -c -o libmkamsboot.o -W -Wall mkamsboot.c |
82 | 42 | ||
83 | bin2c: bin2c.c | 43 | libmkamsboot.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 | ||
86 | clean: | 46 | clean: |
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 | ||
4 | A tool to inject a bootloader into a Sansa V2 (AMS) firmware file. | 4 | A tool to inject a bootloader into a Sansa V2 (AMS) firmware file. |
5 | 5 | ||
6 | See comments in mkamsboot.c and dualboot.S for more information. | 6 | |
7 | Usage | ||
8 | ----- | ||
9 | |||
10 | mkamsboot <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 | |||
22 | Supported models | ||
23 | ---------------- | ||
24 | |||
25 | Sansa Clip : firmware version starting with "01." | ||
26 | Sansa Clipv2: firmware version starting with "02." | ||
27 | Sansa Fuze : firmware version starting with "01." | ||
28 | Sansa E200v2: firmware version starting with "03." | ||
29 | Sansa C200v2: firmware version starting with "03." | ||
30 | Sansa M200v4: firmware version starting with "4." | ||
31 | |||
32 | |||
33 | Firmware filenames | ||
34 | ------------------ | ||
35 | |||
36 | For the firmware upgrade to happen, the firmware has to be named specially: | ||
37 | |||
38 | clip v2 : m30pa.bin | ||
39 | clip : m300a.bin | ||
40 | fuze : fuzea.bin | ||
41 | e200v2 : e200pa.bin | ||
42 | c200v2 : c200pa.bin | ||
43 | m200v4 : m200a.bin | ||
44 | |||
45 | |||
46 | Dual-Boot | ||
47 | --------- | ||
48 | |||
49 | The purpose of this program is to provide dual-boot between the original | ||
50 | firmware 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 | ||
58 | inserting an usb cable. | ||
59 | ***Note : on the m200v4 powering up by usb will cause booting into the new | ||
60 | firmware | ||
61 | |||
62 | Hacking | ||
63 | ------- | ||
64 | |||
65 | 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 @@ | |||
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 | |||
34 | static off_t filesize(int fd) | ||
35 | { | ||
36 | struct stat buf; | ||
37 | |||
38 | fstat(fd,&buf); | ||
39 | return buf.st_size; | ||
40 | } | ||
41 | |||
42 | static 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 | |||
75 | static 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 | |||
93 | int 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 */ | ||
44 | uclunpack_end: .word 0 /* End of the ucl_unpack function */ | ||
45 | uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */ | ||
46 | |||
47 | ucl_of_end: .word 0 /* End of the ucl-compressed OF image */ | ||
48 | ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */ | ||
49 | |||
50 | ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */ | ||
51 | ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */ | ||
52 | |||
53 | |||
54 | start: | ||
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 | |||
62 | uclcopy: | ||
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 | |||
157 | boot_of: | ||
158 | ldr r0, ucl_of_end /* Address of compressed image */ | ||
159 | ldr r1, ucl_of_size /* Compressed size */ | ||
160 | |||
161 | |||
162 | decompress: | ||
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 | |||
171 | fw_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 | |||
3 | unsigned 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 | }; | ||
16 | unsigned 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 | }; | ||
34 | unsigned 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 | }; | ||
51 | unsigned 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 | }; | ||
68 | unsigned 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 | }; | ||
83 | unsigned 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 | }; | ||
100 | unsigned 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 | |||
3 | extern unsigned char nrv2e_d8[168]; | ||
4 | extern unsigned char dualboot_clip[248]; | ||
5 | extern unsigned char dualboot_e200v2[228]; | ||
6 | extern unsigned char dualboot_c200v2[228]; | ||
7 | extern unsigned char dualboot_m200v4[204]; | ||
8 | extern unsigned char dualboot_fuze[228]; | ||
9 | 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 @@ | |||
1 | CC=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 | |||
7 | BOOTOBJS = nrv2e_d8.o dualboot_clip.o dualboot_e200v2.o dualboot_c200v2.o dualboot_m200v4.o dualboot_fuze.o dualboot_clipv2.o | ||
8 | 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 | ||
9 | |||
10 | all: dualboot.h | ||
11 | |||
12 | dualboot.h: $(BOOTBINS) | ||
13 | |||
14 | # Dualboot bootloaders | ||
15 | |||
16 | dualboot_clip.o: dualboot.S | ||
17 | arm-elf-gcc -DSANSA_CLIP -c -o dualboot_clip.o dualboot.S | ||
18 | |||
19 | dualboot_fuze.o: dualboot.S | ||
20 | arm-elf-gcc -DSANSA_FUZE -c -o dualboot_fuze.o dualboot.S | ||
21 | |||
22 | dualboot_e200v2.o: dualboot.S | ||
23 | arm-elf-gcc -DSANSA_E200V2 -c -o dualboot_e200v2.o dualboot.S | ||
24 | |||
25 | dualboot_m200v4.o: dualboot.S | ||
26 | arm-elf-gcc -DSANSA_M200V4 -c -o dualboot_m200v4.o dualboot.S | ||
27 | |||
28 | dualboot_c200v2.o: dualboot.S | ||
29 | arm-elf-gcc -DSANSA_C200V2 -c -o dualboot_c200v2.o dualboot.S | ||
30 | |||
31 | dualboot_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 | ||
35 | nrv2e_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 | |||
47 | dualboot.c dualboot.h: $(BOOTBINS) bin2c | ||
48 | ./bin2c dualboot $(BOOTBINS) | ||
49 | |||
50 | bin2c: bin2c.c | ||
51 | $(CC) -o bin2c bin2c.c | ||
52 | |||
53 | clean: | ||
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 | |||
34 | static off_t filesize(int fd) | ||
35 | { | ||
36 | struct stat buf; | ||
37 | |||
38 | fstat(fd,&buf); | ||
39 | return buf.st_size; | ||
40 | } | ||
41 | |||
42 | static 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 | |||
63 | int 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 | |||
52 | uclunpack_end: .word 0 /* End of the ucl_unpack function */ | ||
53 | uclunpack_size: .word 0 /* Size in bytes of the ucl_unpack function */ | ||
54 | |||
55 | ucl_of_end: .word 0 /* End of the ucl-compressed OF image */ | ||
56 | ucl_of_size: .word 0 /* Size in bytes of the compressed OF image */ | ||
57 | |||
58 | ucl_rb_end: .word 0 /* End of the ucl-compressed RB image */ | ||
59 | ucl_rb_size: .word 0 /* Size in bytes of the compressed RB image */ | ||
60 | |||
61 | |||
62 | start: | ||
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 | |||
70 | uclcopy: | ||
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 */ | ||
144 | 1: 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 | |||
193 | boot_of: | ||
194 | ldr r0, ucl_of_end /* Address of compressed image */ | ||
195 | ldr r1, ucl_of_size /* Compressed size */ | ||
196 | |||
197 | |||
198 | decompress: | ||
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 | |||
207 | fw_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 | /* |
192 | vi:ts=8:et:nowrap | 192 | vi: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 | |||
3 | extract_fw.c - extract the main firmware image from a Sansa V2 (AMS) firmware | ||
4 | file | ||
5 | |||
6 | Copyright (C) Dave Chapman 2008 | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, 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 | |||
41 | static 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 | |||
52 | static uint32_t get_uint32le(unsigned char* p) | ||
53 | { | ||
54 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
55 | } | ||
56 | |||
57 | void usage(void) | ||
58 | { | ||
59 | printf("Usage: extract_fw <firmware file> <output file>\n"); | ||
60 | |||
61 | exit(1); | ||
62 | } | ||
63 | |||
64 | int 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 | ||
27 | Insert a Rockbox bootloader into an AMS original firmware file. | 27 | Insert a Rockbox bootloader into a Sansa AMS original firmware file. |
28 | |||
29 | Layout 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 | ||
29 | We replace the main firmware block (bytes 0x400..0x400+firmware_size) | 39 | We replace the main firmware block (bytes 0x400..0x400+firmware_size) |
30 | as follows: | 40 | as follows: |
@@ -50,9 +60,12 @@ as follows: | |||
50 | 60 | ||
51 | This entire block fits into the space previously occupied by the main | 61 | This entire block fits into the space previously occupied by the main |
52 | firmware block - the space saved by compressing the OF image is used | 62 | firmware block - the space saved by compressing the OF image is used |
53 | to store the compressed version of the Rockbox bootloader. The OF | 63 | to store the compressed version of the Rockbox bootloader. |
54 | image is typically about 120KB, which allows us to store a Rockbox | 64 | |
55 | bootloader with an uncompressed size of about 60KB-70KB. | 65 | On version 1 firmwares, the OF image is typically about 120KB, which allows |
66 | us to store a Rockbox bootloader with an uncompressed size of about 60KB-70KB. | ||
67 | Version 2 firmwares are bigger and are stored in SDRAM (instead of IRAM). | ||
68 | In both cases, the RAM we are using is mapped at offset 0x0. | ||
56 | 69 | ||
57 | mkamsboot then corrects the checksums and writes a new legal firmware | 70 | mkamsboot then corrects the checksums and writes a new legal firmware |
58 | file which can be installed on the device. | 71 | file which can be installed on the device. |
@@ -65,7 +78,7 @@ end of RAM. | |||
65 | 78 | ||
66 | Then, depending on the detection of the dual-boot keypress, either the | 79 | Then, depending on the detection of the dual-boot keypress, either the |
67 | OF image or the Rockbox image is copied to the end of RAM (just before | 80 | OF image or the Rockbox image is copied to the end of RAM (just before |
68 | the ucl unpack function) and uncompress it to the start of RAM. | 81 | the ucl unpack function) and uncompressed to the start of RAM. |
69 | 82 | ||
70 | Finally, the ucl unpack function branches to address 0x0, passing | 83 | Finally, the ucl unpack function branches to address 0x0, passing |
71 | execution to the uncompressed firmware. | 84 | execution 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 | ||
107 | enum | 114 | /* Supported models */ |
108 | { | 115 | enum { |
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 | ||
118 | static const char* model_names[] = | 125 | /* Descriptive name of these models */ |
119 | { | 126 | static 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 | ||
128 | static const unsigned char* bootloaders[] = | 135 | /* Dualboot functions for these models */ |
129 | { | 136 | static 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 | ||
138 | static const int bootloader_sizes[] = | 145 | /* Size of dualboot functions for these models */ |
139 | { | 146 | static 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 */ |
150 | static const char* rb_model_names[] = | 157 | static 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 */ |
162 | static const int rb_model_num[] = | 168 | static 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[] = | |||
172 | struct md5sums { | 177 | struct 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 { | |||
181 | static struct md5sums sansasums[] = { | 186 | static 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[] = { | |||
209 | static off_t filesize(int fd) { | 219 | static 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 | ||
220 | static uint32_t get_uint32le(unsigned char* p) | 230 | static 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 | ||
225 | static uint32_t get_uint32be(unsigned char* p) | 234 | static 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 | ||
230 | static void put_uint32le(unsigned char* p, uint32_t x) | 238 | static 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 | ||
238 | void calc_MD5(unsigned char* buf, int len, char *md5str) | 245 | void 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 */ | |
253 | static uint32_t calc_checksum(unsigned char* buf, uint32_t n) | 259 | static 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 | ||
264 | static int get_model(int model_id) | 269 | static 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 ! */ | |
286 | static unsigned char* uclpack(unsigned char* inbuf, int insize, int* outsize) | 289 | static 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 | ||
320 | static 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 */ | ||
327 | unsigned 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 | ||
406 | error: | ||
407 | free(buf); | ||
408 | return NULL; | ||
409 | } | ||
351 | 410 | ||
352 | static unsigned char* load_rockbox_file(char* filename, int model, off_t* bufsize) | 411 | /* Loads a rockbox bootloader file into memory */ |
353 | { | 412 | unsigned 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 | |||
412 | int 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) { | 466 | error: |
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"); | 474 | void 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 */ | ||
546 | int 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 */ | ||
553 | int 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 | |||
51 | unsigned 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 | |||
79 | unsigned 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 | |||
102 | void 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 | |||
122 | int total_size(int model, int rb_packedsize, int of_packedsize); | ||
123 | |||
124 | #endif | ||