diff options
Diffstat (limited to 'utils/mks5lboot/dualboot')
-rw-r--r-- | utils/mks5lboot/dualboot/.gitignore | 3 | ||||
-rw-r--r-- | utils/mks5lboot/dualboot/Makefile | 97 | ||||
-rw-r--r-- | utils/mks5lboot/dualboot/autoconf.h | 74 | ||||
-rw-r--r-- | utils/mks5lboot/dualboot/bin2c.c | 140 | ||||
-rw-r--r-- | utils/mks5lboot/dualboot/dualboot.c | 287 | ||||
-rw-r--r-- | utils/mks5lboot/dualboot/dualboot.lds | 59 | ||||
-rw-r--r-- | utils/mks5lboot/dualboot/init.S | 43 |
7 files changed, 703 insertions, 0 deletions
diff --git a/utils/mks5lboot/dualboot/.gitignore b/utils/mks5lboot/dualboot/.gitignore new file mode 100644 index 0000000000..34c53b3c82 --- /dev/null +++ b/utils/mks5lboot/dualboot/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | build/ | ||
2 | *.arm-bin | ||
3 | bin2c | ||
diff --git a/utils/mks5lboot/dualboot/Makefile b/utils/mks5lboot/dualboot/Makefile new file mode 100644 index 0000000000..51ce816ca0 --- /dev/null +++ b/utils/mks5lboot/dualboot/Makefile | |||
@@ -0,0 +1,97 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | ifndef V | ||
10 | SILENT = @ | ||
11 | endif | ||
12 | |||
13 | CC = gcc | ||
14 | LD = ld | ||
15 | OC = objcopy | ||
16 | CROSS ?= arm-elf-eabi- | ||
17 | |||
18 | ROOTDIR = ../../.. | ||
19 | FIRMDIR = $(ROOTDIR)/firmware | ||
20 | FWARM = $(FIRMDIR)/target/arm | ||
21 | FW8702 = $(FWARM)/s5l8702 | ||
22 | BUILDDIR = build/ | ||
23 | LINKFILE = dualboot.lds | ||
24 | |||
25 | # Edit the following variables when adding a new target. | ||
26 | # mks5lboot.c also needs to be edited to refer to these | ||
27 | # To add a new target x you need to: | ||
28 | # 1) add x to the list in TARGETS | ||
29 | # 2) create a variable named OPT_x of the form: | ||
30 | # OPT_x=target specific defines | ||
31 | TARGETS = ipod6g | ||
32 | OPT_ipod6g = -DIPOD_6G -DMEMORYSIZE=64 | ||
33 | |||
34 | LOADERS = install uninstall | ||
35 | OPT_install = | ||
36 | OPT_uninstall = -DDUALBOOT_UNINSTALL | ||
37 | |||
38 | # target/loader specific options | ||
39 | $(foreach l, $(LOADERS),$(foreach t, $(TARGETS),\ | ||
40 | $(eval OPT_$(l)_$(t) = $(OPT_$(l)) $(OPT_$(t))))) | ||
41 | |||
42 | DEFINES = -DBOOTLOADER | ||
43 | |||
44 | SOURCES = init.S dualboot.c | ||
45 | SOURCES += $(ROOTDIR)/lib/arm_support/support-arm.S | ||
46 | SOURCES += $(wildcard $(FIRMDIR)/asm/mem*.c $(FIRMDIR)/libc/mem*.c) | ||
47 | SOURCES += $(addprefix $(FWARM)/, mmu-arm.S) | ||
48 | SOURCES += $(addprefix $(FW8702)/, clocking-s5l8702.c spi-s5l8702.c nor-s5l8702.c crypto-s5l8702.c) | ||
49 | # target/loader specific sources | ||
50 | SRCTARGET = piezo-.c | ||
51 | $(foreach l, $(LOADERS), $(foreach t, $(TARGETS),\ | ||
52 | $(eval SRC_$(l)_$(t) = $(addprefix $(FW8702)/$(t)/, $(subst -.,-$(subst ipod,,$(t)).,$(SRCTARGET)))))) | ||
53 | |||
54 | INCLUDES += -I. -I.. -I$(FIRMDIR) -I$(FWARM) -I$(FW8702) | ||
55 | INCLUDES += $(addprefix -I$(FIRMDIR)/, export include libc/include kernel/include) | ||
56 | # target/loader specific includes | ||
57 | $(foreach l,$(LOADERS),$(foreach t,$(TARGETS),$(eval INC_$(l)_$(t) = -I$(FW8702)/$(t)))) | ||
58 | |||
59 | CFLAGS = $(INCLUDES) -mcpu=arm926ej-s -std=gnu99 -nostdlib -ffreestanding -Os -W -Wall\ | ||
60 | -Wundef -Wstrict-prototypes -ffunction-sections -fdata-sections -Wl,--gc-sections $(DEFINES) | ||
61 | |||
62 | # Build filenames prefix | ||
63 | PFX = dualboot_ | ||
64 | |||
65 | BOOTBINS = $(foreach l, $(LOADERS),$(foreach t, $(TARGETS),$(PFX)$(l)_$(t).arm-bin)) | ||
66 | |||
67 | OUTPUTDUALBOOT = ../dualboot.h ../dualboot.c | ||
68 | OUTPUTDEBUG = $(BOOTBINS:%.arm-bin=$(BUILDDIR)%.arm-elf) $(BOOTBINS:%.arm-bin=$(BUILDDIR)%.lds) | ||
69 | |||
70 | |||
71 | all: $(BUILDDIR) $(OUTPUTDUALBOOT) | ||
72 | |||
73 | $(BUILDDIR)$(PFX)%.lds: $(LINKFILE) | ||
74 | @echo Creating $@ | ||
75 | $(SILENT)$(CROSS)$(CC) $(INC_$*) $(CFLAGS) $(OPT_$*) -E -x c - < $< | sed '/#/d' > $@ | ||
76 | |||
77 | $(BUILDDIR)$(PFX)%.arm-elf: $(BUILDDIR)$(PFX)%.lds $(SOURCES) | ||
78 | @echo CC -T $(notdir $^ $(SRC_$*)) | ||
79 | $(SILENT)$(CROSS)$(CC) $(INC_$*) $(CFLAGS) $(OPT_$*) -o $@ -T$^ $(SRC_$*) | ||
80 | |||
81 | $(PFX)%.arm-bin: $(BUILDDIR)$(PFX)%.arm-elf | ||
82 | @echo OC $< | ||
83 | $(SILENT)$(CROSS)$(OC) -O binary $< $@ | ||
84 | |||
85 | bin2c: bin2c.c | ||
86 | $(CC) -o $@ $< | ||
87 | |||
88 | $(OUTPUTDUALBOOT): bin2c $(BOOTBINS) | ||
89 | ./bin2c ../dualboot $(BOOTBINS) | ||
90 | |||
91 | $(BUILDDIR): | ||
92 | mkdir -p $@ | ||
93 | |||
94 | clean: | ||
95 | rm -rf bin2c $(BOOTBINS) $(BUILDDIR) | ||
96 | |||
97 | .PRECIOUS: $(OUTPUTDEBUG) | ||
diff --git a/utils/mks5lboot/dualboot/autoconf.h b/utils/mks5lboot/dualboot/autoconf.h new file mode 100644 index 0000000000..cd5b3f9aeb --- /dev/null +++ b/utils/mks5lboot/dualboot/autoconf.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id:$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Andrew Ryabinin | ||
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 | #ifndef __BUILD_AUTOCONF_H | ||
22 | #define __BUILD_AUTOCONF_H | ||
23 | |||
24 | /* lower case names match the what's exported in the Makefile | ||
25 | * upper case name looks nicer in the code */ | ||
26 | |||
27 | #define arch_none 0 | ||
28 | #define ARCH_NONE 0 | ||
29 | |||
30 | #define arch_sh 1 | ||
31 | #define ARCH_SH 1 | ||
32 | |||
33 | #define arch_m68k 2 | ||
34 | #define ARCH_M68K 2 | ||
35 | |||
36 | #define arch_arm 3 | ||
37 | #define ARCH_ARM 3 | ||
38 | |||
39 | #define arch_mips 4 | ||
40 | #define ARCH_MIPS 4 | ||
41 | |||
42 | #define arch_x86 5 | ||
43 | #define ARCH_X86 5 | ||
44 | |||
45 | #define arch_amd64 6 | ||
46 | #define ARCH_AMD64 6 | ||
47 | |||
48 | /* Define target machine architecture */ | ||
49 | #define ARCH arch_arm | ||
50 | /* Optionally define architecture version */ | ||
51 | #define ARCH_VERSION 5 | ||
52 | |||
53 | /* Define endianess for the target or simulator platform */ | ||
54 | #define ROCKBOX_LITTLE_ENDIAN 1 | ||
55 | |||
56 | /* Define this if you build rockbox to support the logf logging and display */ | ||
57 | #undef ROCKBOX_HAS_LOGF | ||
58 | |||
59 | /* Define this if you want logf to output to the serial port */ | ||
60 | #undef LOGF_SERIAL | ||
61 | |||
62 | /* Define this to record a chart with timings for the stages of boot */ | ||
63 | #undef DO_BOOTCHART | ||
64 | |||
65 | /* the threading backend we use */ | ||
66 | #define ASSEMBLER_THREADS | ||
67 | |||
68 | /* root of Rockbox */ | ||
69 | #define ROCKBOX_DIR "/.rockbox" | ||
70 | #define ROCKBOX_SHARE_PATH "" | ||
71 | #define ROCKBOX_BINARY_PATH "" | ||
72 | #define ROCKBOX_LIBRARY_PATH "" | ||
73 | |||
74 | #endif /* __BUILD_AUTOCONF_H */ | ||
diff --git a/utils/mks5lboot/dualboot/bin2c.c b/utils/mks5lboot/dualboot/bin2c.c new file mode 100644 index 0000000000..4d74a19696 --- /dev/null +++ b/utils/mks5lboot/dualboot/bin2c.c | |||
@@ -0,0 +1,140 @@ | |||
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 | #include <libgen.h> | ||
30 | |||
31 | #ifndef O_BINARY | ||
32 | #define O_BINARY 0 | ||
33 | #endif | ||
34 | |||
35 | static off_t filesize(int fd) | ||
36 | { | ||
37 | struct stat buf; | ||
38 | |||
39 | fstat(fd,&buf); | ||
40 | return buf.st_size; | ||
41 | } | ||
42 | |||
43 | static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name) | ||
44 | { | ||
45 | int i; | ||
46 | |||
47 | fprintf(fp,"unsigned char %s[%ld] = {",name,len); | ||
48 | |||
49 | for (i=0;i<len;i++) { | ||
50 | if ((i % 16) == 0) { | ||
51 | fprintf(fp,"\n "); | ||
52 | } | ||
53 | if (i == (len-1)) { | ||
54 | fprintf(fp,"0x%02x",buf[i]); | ||
55 | } else if ((i % 16) == 15) { | ||
56 | fprintf(fp,"0x%02x,",buf[i]); | ||
57 | } else { | ||
58 | fprintf(fp,"0x%02x, ",buf[i]); | ||
59 | } | ||
60 | } | ||
61 | fprintf(fp,"\n};\n"); | ||
62 | } | ||
63 | |||
64 | int main (int argc, char* argv[]) | ||
65 | { | ||
66 | char* cname; | ||
67 | int i; | ||
68 | FILE *cfile, *hfile; | ||
69 | char cfilename[256], hfilename[256]; | ||
70 | |||
71 | if (argc < 3) { | ||
72 | fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n"); | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | cname=argv[1]; | ||
77 | |||
78 | snprintf(cfilename,256,"%s.c",cname); | ||
79 | cfile = fopen(cfilename,"w+"); | ||
80 | if (cfile == NULL) { | ||
81 | fprintf(stderr,"Couldn't open %s\n",cfilename); | ||
82 | return 2; | ||
83 | } | ||
84 | |||
85 | snprintf(hfilename,256,"%s.h",cname); | ||
86 | hfile = fopen(hfilename,"w+"); | ||
87 | if (hfile == NULL) { | ||
88 | fprintf(stderr,"Couldn't open %s\n",hfilename); | ||
89 | fclose(cfile); | ||
90 | return 3; | ||
91 | } | ||
92 | |||
93 | fprintf(cfile,"/* Generated by bin2c */\n\n"); | ||
94 | fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename)); | ||
95 | fprintf(hfile,"/* Generated by bin2c */\n\n"); | ||
96 | |||
97 | for(i=0; i < argc - 2; i++) { | ||
98 | unsigned char* buf; | ||
99 | off_t len; | ||
100 | off_t orig_len; | ||
101 | char *ext; | ||
102 | char *array = argv[2+i]; | ||
103 | |||
104 | int fd = open(array,O_RDONLY|O_BINARY); | ||
105 | if (fd < 0) { | ||
106 | fprintf(stderr,"Can not open %s\n",argv[2+i]); | ||
107 | fclose(cfile); | ||
108 | fclose(hfile); | ||
109 | return 4; | ||
110 | } | ||
111 | |||
112 | orig_len = filesize(fd); | ||
113 | /* pad to 32bit */ | ||
114 | len = (orig_len + 3) & ~3; | ||
115 | |||
116 | buf = malloc(len); | ||
117 | if (read(fd,buf,orig_len) < orig_len) { | ||
118 | fprintf(stderr,"Short read, aborting\n"); | ||
119 | return 5; | ||
120 | } | ||
121 | |||
122 | /* pad to 32bit with zeros */ | ||
123 | if (len > orig_len) | ||
124 | memset(buf+orig_len, 0, len-orig_len); | ||
125 | |||
126 | /* remove file extension */ | ||
127 | ext = strchr (array, '.'); | ||
128 | if (ext != NULL) | ||
129 | *ext = '\0'; | ||
130 | write_cfile (buf, len, cfile, array); | ||
131 | fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len); | ||
132 | |||
133 | close(fd); | ||
134 | } | ||
135 | |||
136 | fclose(cfile); | ||
137 | fclose(hfile); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
diff --git a/utils/mks5lboot/dualboot/dualboot.c b/utils/mks5lboot/dualboot/dualboot.c new file mode 100644 index 0000000000..b8167ec124 --- /dev/null +++ b/utils/mks5lboot/dualboot/dualboot.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2015 by Cástor Muñoz | ||
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 | #include <stdint.h> | ||
22 | #include <string.h> | ||
23 | |||
24 | #include "config.h" | ||
25 | #include "system.h" | ||
26 | #include "button.h" | ||
27 | |||
28 | #include "s5l8702.h" | ||
29 | #include "clocking-s5l8702.h" | ||
30 | #include "spi-s5l8702.h" | ||
31 | #include "nor-target.h" | ||
32 | #include "piezo.h" | ||
33 | |||
34 | /* How it works: | ||
35 | * | ||
36 | * - dualboot-installer: installs or updates a RB bootloader, the bootloader | ||
37 | * to install/update is already included into dualboot-installer.dfu file, | ||
38 | * once it is executed by the iPod device: | ||
39 | * | ||
40 | * 1) locates an original NORBOOT (ONB): first it looks at offset=32KB, if | ||
41 | * a NORBOOT is found but it is not an ONB then it is supposed it is a | ||
42 | * RB bootloader (that should be updated), then the ONB is loaded from | ||
43 | * offset=32KB+old_BLSIZE). | ||
44 | * 2) write ONB at 32KB+new_BLSIZE, if it fails then: | ||
45 | * 2a) try to restore ONB to its 'pristine' place (offset=32KB), if it | ||
46 | * also fails then the NOR got corrupted (ONB probably destroyed) | ||
47 | * and iTunes should be used to restore the iPod. | ||
48 | * 3) write new (included) RB bootloader at offset=32KB, it it fails then | ||
49 | * goto 2a) | ||
50 | * | ||
51 | * - dualboot-uninstaller: uninstall RB bootloader from NOR, leaving it at | ||
52 | * it's previous (pristine) state. | ||
53 | * | ||
54 | * See bootloader/ipod6g.c for notes on how the RB bootloader works. | ||
55 | * | ||
56 | * | ||
57 | * Pristine NOR Rockboxed NOR | ||
58 | * 1MB ______________ | ||
59 | * | | | ||
60 | * | flsh DIR | | ||
61 | * 1MB-0x200 |______________| | ||
62 | * | | | ||
63 | * | File 1 | | ||
64 | * |..............| | ||
65 | * | | | ||
66 | * . . | ||
67 | * . . | ||
68 | * . . | ||
69 | * | | | ||
70 | * |..............| | ||
71 | * | | . . | ||
72 | * | File N | . . | ||
73 | * |______________| |______________| | ||
74 | * | | | | | ||
75 | * | | | | | ||
76 | * | | | Unused | | ||
77 | * | | | | | ||
78 | * | Unused | 160KB+BLSZ |______________| | ||
79 | * | | | | | ||
80 | * | | | Original | | ||
81 | * | | | NOR boot | | ||
82 | * 160KB |______________| | (decrypted) | | ||
83 | * | | | | | ||
84 | * | | 32KB+BLSZ |______________| | ||
85 | * | Original | | | | ||
86 | * | NOR boot | | Decrypted | | ||
87 | * | (encrypted) | | Rockbox | | ||
88 | * | | | Bootloader | | ||
89 | * 32KB |______________| 32KB |______________| | ||
90 | * | | | | | ||
91 | * | | . . | ||
92 | * | | . . | ||
93 | * |______________| | ||
94 | * | | | ||
95 | * | SysCfg | | ||
96 | * 0 |______________| | ||
97 | * | ||
98 | */ | ||
99 | |||
100 | #define OF_LOADADDR IRAM1_ORIG | ||
101 | |||
102 | /* tone sequences: period (uS), duration (ms), silence (ms) */ | ||
103 | static uint16_t alive[] = { 500,100,0, 0 }; | ||
104 | static uint16_t happy[] = { 1000,100,0, 500,150,0, 0 }; | ||
105 | static uint16_t fatal[] = { 3000,500,500, 3000,500,500, 3000,500,0, 0 }; | ||
106 | #define sad2 (&fatal[3]) | ||
107 | #define sad (&fatal[6]) | ||
108 | |||
109 | /* iPod Classic: decrypted hashes for known OFs */ | ||
110 | static unsigned char of_sha[][SIGN_SZ] = { | ||
111 | "\x66\x66\x76\xDC\x1D\x32\xB2\x46\xA6\xC9\x7D\x5A\x61\xD3\x49\x4C", /* v1.1.2 */ | ||
112 | "\x1E\xF0\xD9\xDE\xC2\x7E\xEC\x02\x7C\x15\x76\xBB\x5C\x4F\x2D\x95", /* v2.0.1 */ | ||
113 | "\x06\x85\xDF\x28\xE4\xD7\xF4\x82\xC0\x73\xB0\x53\x26\xFC\xB0\xFE", /* v2.0.4 */ | ||
114 | "\x60\x80\x7D\x33\xA8\xDE\xF8\x49\xBB\xBE\x01\x45\xFF\x62\x40\x19" /* v2.0.5 */ | ||
115 | }; | ||
116 | #define N_OF (int)(sizeof(of_sha)/SIGN_SZ) | ||
117 | |||
118 | /* we can assume that unknown FW is a RB bootloader */ | ||
119 | #define FW_RB N_OF | ||
120 | |||
121 | static int identify_fw(struct Im3Info *hinfo) | ||
122 | { | ||
123 | unsigned char hash[SIGN_SZ]; | ||
124 | int of; | ||
125 | |||
126 | /* decrypt hash to identify OF */ | ||
127 | memcpy(hash, hinfo->u.enc12.data_sign, SIGN_SZ); | ||
128 | hwkeyaes(HWKEYAES_DECRYPT, HWKEYAES_UKEY, hash, SIGN_SZ); | ||
129 | |||
130 | for (of = 0; of < N_OF; of++) | ||
131 | if (memcmp(hash, of_sha[of], SIGN_SZ) == 0) | ||
132 | break; | ||
133 | |||
134 | return of; | ||
135 | } | ||
136 | |||
137 | #ifdef DUALBOOT_UNINSTALL | ||
138 | /* Uninstall RB bootloader */ | ||
139 | void main(void) | ||
140 | { | ||
141 | struct Im3Info *hinfo; | ||
142 | void *fw_addr; | ||
143 | uint16_t *status; | ||
144 | unsigned bl_nor_sz; | ||
145 | |||
146 | usec_timer_init(); | ||
147 | piezo_seq(alive); | ||
148 | spi_clkdiv(SPI_PORT, 4); /* SPI clock = 27/5 MHz. */ | ||
149 | |||
150 | hinfo = (struct Im3Info*)OF_LOADADDR; | ||
151 | fw_addr = (void*)hinfo + IM3HDR_SZ; | ||
152 | |||
153 | if (im3_read(NORBOOT_OFF, hinfo, NULL) != 0) { | ||
154 | status = sad; | ||
155 | goto bye; /* no FW found */ | ||
156 | } | ||
157 | |||
158 | if (identify_fw(hinfo) != FW_RB) { | ||
159 | status = happy; | ||
160 | goto bye; /* RB bootloader not installed, nothing to do */ | ||
161 | } | ||
162 | |||
163 | /* if found FW is a RB bootloader, OF should start just behind it */ | ||
164 | bl_nor_sz = im3_nor_sz(hinfo); | ||
165 | if ((im3_read(NORBOOT_OFF + bl_nor_sz, hinfo, fw_addr) != 0) | ||
166 | || (identify_fw(hinfo) == FW_RB)) { | ||
167 | status = sad; | ||
168 | goto bye; /* OF not found */ | ||
169 | } | ||
170 | |||
171 | /* decrypted OF correctly loaded, encrypt it before restoration */ | ||
172 | im3_crypt(HWKEYAES_ENCRYPT, hinfo, fw_addr); | ||
173 | |||
174 | /* restore OF to it's original place */ | ||
175 | if (!im3_write(NORBOOT_OFF, hinfo)) { | ||
176 | status = fatal; | ||
177 | goto bye; /* corrupted NOR, use iTunes to restore */ | ||
178 | } | ||
179 | |||
180 | /* erase freed NOR blocks */ | ||
181 | bootflash_init(SPI_PORT); | ||
182 | bootflash_erase_blocks(SPI_PORT, | ||
183 | (NORBOOT_OFF + im3_nor_sz(hinfo)) >> 12, bl_nor_sz >> 12); | ||
184 | bootflash_close(SPI_PORT); | ||
185 | |||
186 | status = happy; | ||
187 | |||
188 | bye: | ||
189 | /* minimum time between the initial and the final beeps */ | ||
190 | while (USEC_TIMER < 2000000); | ||
191 | piezo_seq(status); | ||
192 | WDTCON = 0x100000; /* WDT reset */ | ||
193 | while (1); | ||
194 | } | ||
195 | |||
196 | #else | ||
197 | /* Install RB bootloader */ | ||
198 | struct Im3Info bl_hinfo __attribute__((section(".im3info.data"))) = | ||
199 | { | ||
200 | .ident = IM3_IDENT, | ||
201 | .version = IM3_VERSION, | ||
202 | .enc_type = 2, | ||
203 | }; | ||
204 | |||
205 | static uint32_t get_uint32le(unsigned char *p) | ||
206 | { | ||
207 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
208 | } | ||
209 | |||
210 | void main(void) | ||
211 | { | ||
212 | uint16_t *status = happy; | ||
213 | int single_boot; | ||
214 | struct Im3Info *hinfo; | ||
215 | void *fw_addr; | ||
216 | unsigned bl_nor_sz; | ||
217 | |||
218 | usec_timer_init(); | ||
219 | piezo_seq(alive); | ||
220 | spi_clkdiv(SPI_PORT, 4); /* SPI clock = 27/5 MHz. */ | ||
221 | |||
222 | /* check for single boot installation, is is configured when | ||
223 | mks5lboot.exe builds the .dfu image */ | ||
224 | single_boot = bl_hinfo.info_sign[0]; | ||
225 | |||
226 | /* sign RB bootloader (data and header), but don't encrypt it, | ||
227 | use current decrypted image for faster load */ | ||
228 | im3_sign(HWKEYAES_UKEY, (void*)&bl_hinfo + IM3HDR_SZ, | ||
229 | get_uint32le(bl_hinfo.data_sz), bl_hinfo.u.enc12.data_sign); | ||
230 | im3_sign(HWKEYAES_UKEY, &bl_hinfo, IM3INFOSIGN_SZ, bl_hinfo.info_sign); | ||
231 | |||
232 | if (single_boot) { | ||
233 | if (!im3_write(NORBOOT_OFF, &bl_hinfo)) | ||
234 | status = sad; | ||
235 | goto bye; | ||
236 | } | ||
237 | |||
238 | hinfo = (struct Im3Info*)OF_LOADADDR; | ||
239 | fw_addr = (void*)hinfo + IM3HDR_SZ; | ||
240 | |||
241 | if (im3_read(NORBOOT_OFF, hinfo, fw_addr) != 0) { | ||
242 | status = sad; | ||
243 | goto bye; /* no FW found */ | ||
244 | } | ||
245 | |||
246 | if (identify_fw(hinfo) == FW_RB) { | ||
247 | /* FW found, but not OF, assume it is a RB bootloader, | ||
248 | already decrypted OF should be located just behind */ | ||
249 | int nor_offset = NORBOOT_OFF + im3_nor_sz(hinfo); | ||
250 | if ((im3_read(nor_offset, hinfo, fw_addr) != 0) | ||
251 | || (identify_fw(hinfo) == FW_RB)) { | ||
252 | status = sad; | ||
253 | goto bye; /* OF not found, use iTunes to restore */ | ||
254 | } | ||
255 | } | ||
256 | |||
257 | bl_nor_sz = im3_nor_sz(&bl_hinfo); | ||
258 | /* safety check - verify we are not going to overwrite useful data */ | ||
259 | if (flsh_get_unused() < bl_nor_sz) { | ||
260 | status = sad2; | ||
261 | goto bye; /* no space if flash, use iTunes to restore */ | ||
262 | } | ||
263 | |||
264 | /* write decrypted OF and RB bootloader, if any of these fails we | ||
265 | will try to retore OF to its original place */ | ||
266 | if (!im3_write(NORBOOT_OFF + bl_nor_sz, hinfo) | ||
267 | || !im3_write(NORBOOT_OFF, &bl_hinfo)) { | ||
268 | im3_crypt(HWKEYAES_ENCRYPT, hinfo, fw_addr); | ||
269 | if (!im3_write(NORBOOT_OFF, hinfo)) { | ||
270 | /* corrupted NOR, use iTunes to restore */ | ||
271 | status = fatal; | ||
272 | } | ||
273 | else { | ||
274 | /* RB bootloader not succesfully intalled, but device | ||
275 | was restored and should be working as before */ | ||
276 | status = sad; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | bye: | ||
281 | /* minimum time between the initial and the final beeps */ | ||
282 | while (USEC_TIMER < 2000000); | ||
283 | piezo_seq(status); | ||
284 | WDTCON = 0x100000; /* WDT reset */ | ||
285 | while (1); | ||
286 | } | ||
287 | #endif /* DUALBOOT_UNINSTALL */ | ||
diff --git a/utils/mks5lboot/dualboot/dualboot.lds b/utils/mks5lboot/dualboot/dualboot.lds new file mode 100644 index 0000000000..cb92e2a286 --- /dev/null +++ b/utils/mks5lboot/dualboot/dualboot.lds | |||
@@ -0,0 +1,59 @@ | |||
1 | #define ASM | ||
2 | #include "config.h" | ||
3 | #include "cpu.h" | ||
4 | #include "mks5lboot.h" | ||
5 | |||
6 | ENTRY(_start) | ||
7 | OUTPUT_FORMAT(elf32-littlearm) | ||
8 | OUTPUT_ARCH(arm) | ||
9 | |||
10 | #define BIN_ORIG DFU_LOADADDR + BIN_OFFSET | ||
11 | #define BIN_SIZE MAX_PAYLOAD | ||
12 | |||
13 | MEMORY | ||
14 | { | ||
15 | IRAM : ORIGIN = BIN_ORIG, LENGTH = BIN_SIZE | ||
16 | } | ||
17 | |||
18 | SECTIONS | ||
19 | { | ||
20 | .text : { | ||
21 | *(.init.text*) | ||
22 | *(.text*) | ||
23 | *(.icode*) | ||
24 | . = ALIGN(4); | ||
25 | } > IRAM | ||
26 | |||
27 | /* include initialized BSS (if any) into DFU image */ | ||
28 | .bss : { | ||
29 | *(.bss*) | ||
30 | *(.ibss*) | ||
31 | *(COMMON) | ||
32 | . = ALIGN(4); | ||
33 | } > IRAM | ||
34 | |||
35 | #if 1 | ||
36 | /* reuse pwnage as stack, 0x30c bytes available */ | ||
37 | _exception_stack = BIN_ORIG; | ||
38 | _supervisor_stack = _exception_stack; | ||
39 | #else | ||
40 | /* include stack into DFU image */ | ||
41 | .stack : { | ||
42 | . += 0x400; | ||
43 | _supervisor_stack = .; | ||
44 | . += 0x200; | ||
45 | _exception_stack = .; | ||
46 | } > IRAM | ||
47 | #endif | ||
48 | |||
49 | .data : { | ||
50 | *(.data*) | ||
51 | *(.rodata*) | ||
52 | *(.idata*) | ||
53 | *(.irodata*) | ||
54 | /* place bootloader IM3 header at the end, mkdfu | ||
55 | will concatenate the bootloader binary here */ | ||
56 | . = ALIGN(16); | ||
57 | *(.im3info.data*) | ||
58 | } > IRAM | ||
59 | } | ||
diff --git a/utils/mks5lboot/dualboot/init.S b/utils/mks5lboot/dualboot/init.S new file mode 100644 index 0000000000..bd049515f4 --- /dev/null +++ b/utils/mks5lboot/dualboot/init.S | |||
@@ -0,0 +1,43 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: | ||
9 | * | ||
10 | * Copyright © 2009 Michael Sparmann | ||
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 | .section .init.text, "ax", %progbits | ||
23 | .global _start | ||
24 | |||
25 | _start: | ||
26 | mov r0, #0xD7 | ||
27 | msr CPSR_c, r0 @ Abort mode, IRQs/FIQs disabled | ||
28 | ldr sp, =_exception_stack | ||
29 | |||
30 | mov r0, #0xDB | ||
31 | msr CPSR_c, r0 @ Undefined Instruction mode, IRQs/FIQs disabled | ||
32 | ldr sp, =_exception_stack | ||
33 | |||
34 | mov r0, #0xD3 | ||
35 | msr CPSR_c, r0 @ Supervisor mode, IRQs/FIQs disabled | ||
36 | ldr sp, =_supervisor_stack | ||
37 | |||
38 | MOV R0, #0x00050000 | ||
39 | ORR R0, #0x00000078 | ||
40 | MCR p15, 0, R0, c1, c0, 0 @ Get rid of some CPU "features" likely to cause trouble | ||
41 | |||
42 | bl main | ||
43 | .ltorg | ||