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