summaryrefslogtreecommitdiff
path: root/utils/mkimxboot
diff options
context:
space:
mode:
Diffstat (limited to 'utils/mkimxboot')
-rw-r--r--utils/mkimxboot/Makefile46
-rw-r--r--utils/mkimxboot/dualboot.c293
-rw-r--r--utils/mkimxboot/dualboot.h8
-rw-r--r--utils/mkimxboot/dualboot/Makefile48
-rw-r--r--utils/mkimxboot/dualboot/bin2c.c140
-rw-r--r--utils/mkimxboot/dualboot/config.h26
-rw-r--r--utils/mkimxboot/dualboot/dualboot.c323
-rw-r--r--utils/mkimxboot/dualboot/dualboot.lds17
-rw-r--r--utils/mkimxboot/main.c289
-rw-r--r--utils/mkimxboot/md5.c246
-rw-r--r--utils/mkimxboot/md5.h25
-rw-r--r--utils/mkimxboot/mkimxboot.c1123
-rw-r--r--utils/mkimxboot/mkimxboot.h116
13 files changed, 2700 insertions, 0 deletions
diff --git a/utils/mkimxboot/Makefile b/utils/mkimxboot/Makefile
new file mode 100644
index 0000000000..966423159a
--- /dev/null
+++ b/utils/mkimxboot/Makefile
@@ -0,0 +1,46 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7
8# We use the SB code available in the Rockbox utils/sbtools directory
9
10IMXTOOLS_DIR=../../utils/imxtools/sbtools/
11
12COMPILEFLAGS := -Wall -g -O3 -I$(IMXTOOLS_DIR)
13
14# std=gnu99 is required by MinGW on Windows (c99 is sufficient for Linux / MXE)
15CFLAGS += -std=gnu99 $(COMPILEFLAGS)
16
17TOMCRYPT_DIR := ../../utils/tomcrypt
18
19CFLAGS += -I$(TOMCRYPT_DIR)/src/headers
20LDOPTS += -lpthread $(TOMCRYPT_DIR)/librbtomcrypt.a
21
22OUTPUT = mkimxboot
23
24# inputs for lib
25IMXTOOLS_SOURCES = misc.c sb.c crypto.c crc.c elf.c
26LIBSOURCES := dualboot.c mkimxboot.c md5.c \
27 $(addprefix $(IMXTOOLS_DIR),$(IMXTOOLS_SOURCES))
28
29# for now build tomcrypt as part of the lib.
30LIBSOURCES += $(addprefix $(TOMCRYPT_DIR),$(TOMCRYPT_SOURCES))
31
32# inputs for binary only
33SOURCES := $(LIBSOURCES) main.c
34# dependencies for binary
35EXTRADEPS :=
36
37include ../libtools.make
38
39# explicit dependencies on dualboot.{c,h} and mkimxboot.h
40$(OBJDIR)mkimxboot.o: dualboot.h dualboot.c mkimxboot.c mkimxboot.h
41$(OBJDIR)main.o: dualboot.h dualboot.c main.c mkimxboot.h
42$(BINARY): librbtomcrypt.a
43
44librbtomcrypt.a:
45 $(MAKE) -C ../../utils/tomcrypt
46
diff --git a/utils/mkimxboot/dualboot.c b/utils/mkimxboot/dualboot.c
new file mode 100644
index 0000000000..dd43a63d2d
--- /dev/null
+++ b/utils/mkimxboot/dualboot.c
@@ -0,0 +1,293 @@
1/* Generated by bin2c */
2
3#include "dualboot.h"
4
5unsigned char dualboot_fuzeplus[728] = {
6 0x10, 0x40, 0x2d, 0xe9, 0x30, 0x00, 0x00, 0xeb, 0x10, 0x80, 0xbd, 0xe8, 0x40, 0x30, 0x9f, 0xe5,
7 0xb0, 0x30, 0x93, 0xe5, 0x03, 0x18, 0xa0, 0xe1, 0x21, 0x18, 0xa0, 0xe1, 0x34, 0x20, 0x9f, 0xe5,
8 0x02, 0x00, 0x51, 0xe1, 0x08, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x50, 0xe3, 0x01, 0x38, 0x03, 0x02,
9 0x23, 0x08, 0xa0, 0x01, 0x1e, 0xff, 0x2f, 0x01, 0x01, 0x00, 0x50, 0xe3, 0x02, 0x00, 0x00, 0x1a,
10 0x06, 0x38, 0x03, 0xe2, 0xa3, 0x08, 0xa0, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0xa0, 0xe3,
11 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x04, 0x40, 0x2d, 0xe5,
12 0x5c, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x92, 0xe5, 0x03, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xa0, 0xe1,
13 0x50, 0x20, 0x9f, 0xe5, 0x02, 0x00, 0x54, 0xe1, 0x02, 0x30, 0xa0, 0x11, 0x00, 0x00, 0x50, 0xe3,
14 0x02, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe3, 0x09, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0xea,
15 0x01, 0x38, 0xc3, 0xe3, 0x01, 0x18, 0xa0, 0xe1, 0x01, 0x18, 0x01, 0xe2, 0x01, 0x30, 0x83, 0xe1,
16 0x03, 0x00, 0x00, 0xea, 0x06, 0x38, 0xc3, 0xe3, 0x81, 0x18, 0xa0, 0xe1, 0x06, 0x18, 0x01, 0xe2,
17 0x01, 0x30, 0x83, 0xe1, 0x08, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x82, 0xe5, 0x10, 0x00, 0xbd, 0xe8,
18 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x70, 0x40, 0x2d, 0xe9,
19 0x00, 0x40, 0xa0, 0xe1, 0x01, 0x60, 0xa0, 0xe1, 0xd8, 0x31, 0x9f, 0xe5, 0x03, 0x00, 0x50, 0xe1,
20 0x34, 0x00, 0x00, 0x1a, 0xd0, 0x31, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5,
21 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
22 0x02, 0x21, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x0f, 0x28, 0xc2, 0xe3,
23 0x01, 0x28, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x7f, 0x2e, 0xc2, 0xe3,
24 0x0f, 0x20, 0xc2, 0xe3, 0xc8, 0x20, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0x01, 0x26, 0xa0, 0xe3,
25 0xd4, 0x20, 0x83, 0xe5, 0x34, 0x21, 0x83, 0xe5, 0x30, 0x11, 0x93, 0xe5, 0x03, 0x18, 0xc1, 0xe3,
26 0x02, 0x18, 0x81, 0xe3, 0x30, 0x11, 0x83, 0xe5, 0x03, 0x39, 0x43, 0xe2, 0x30, 0x10, 0x93, 0xe5,
27 0x0f, 0x1c, 0xc1, 0xe3, 0x01, 0x1c, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x30, 0x10, 0x93, 0xe5,
28 0x3f, 0x10, 0xc1, 0xe3, 0x10, 0x10, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x01, 0x18, 0xa0, 0xe3,
29 0x38, 0x10, 0x83, 0xe5, 0x80, 0x10, 0x93, 0xe5, 0x02, 0x15, 0x81, 0xe3, 0x80, 0x10, 0x83, 0xe5,
30 0x18, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5, 0x3f, 0x2a, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3,
31 0x10, 0x20, 0x83, 0xe5, 0x01, 0x39, 0x43, 0xe2, 0x00, 0x10, 0xa0, 0xe3, 0x20, 0x20, 0x93, 0xe5,
32 0x01, 0x2a, 0x82, 0xe3, 0x20, 0x20, 0x83, 0xe5, 0x90, 0x1f, 0x07, 0xee, 0x00, 0x00, 0xa0, 0xe1,
33 0x00, 0x00, 0xa0, 0xe1, 0xf8, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
34 0xa5, 0xff, 0xff, 0xeb, 0x01, 0x00, 0xa0, 0xe3, 0x8f, 0xff, 0xff, 0xeb, 0x00, 0x50, 0xa0, 0xe1,
35 0x01, 0x00, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0x9f, 0xff, 0xff, 0xeb, 0x01, 0x00, 0x55, 0xe3,
36 0x25, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x55, 0xe3, 0x04, 0x00, 0x00, 0x1a, 0x01, 0x27, 0xa0, 0xe3,
37 0xc8, 0x30, 0x9f, 0xe5, 0x78, 0x20, 0x83, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8,
38 0xbc, 0x30, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5, 0x3f, 0x34, 0x03, 0xe2, 0x23, 0x3c, 0xa0, 0xe1,
39 0x20, 0x00, 0x13, 0xe3, 0x01, 0x30, 0xa0, 0x13, 0x02, 0x00, 0x00, 0x1a, 0x10, 0x00, 0x13, 0xe3,
40 0x02, 0x30, 0xa0, 0x13, 0x00, 0x30, 0xa0, 0x03, 0x98, 0x20, 0x9f, 0xe5, 0x10, 0x26, 0x92, 0xe5,
41 0x01, 0x01, 0x12, 0xe3, 0x10, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x53, 0xe3, 0x10, 0x00, 0x00, 0x1a,
42 0x03, 0x20, 0xa0, 0xe1, 0x78, 0x00, 0x9f, 0xe5, 0x7c, 0x10, 0x9f, 0xe5, 0xc0, 0xc0, 0x90, 0xe5,
43 0x03, 0xc6, 0x0c, 0xe2, 0x01, 0x06, 0x5c, 0xe3, 0x01, 0x20, 0x82, 0x02, 0x01, 0x30, 0x83, 0xe2,
44 0x01, 0x00, 0x53, 0xe1, 0xf8, 0xff, 0xff, 0x1a, 0x60, 0x30, 0x9f, 0xe5, 0x03, 0x00, 0x52, 0xe1,
45 0x03, 0x00, 0x00, 0xca, 0x05, 0x00, 0x00, 0xea, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3,
46 0x70, 0x80, 0xbd, 0xe8, 0x00, 0x40, 0x86, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8,
47 0x30, 0x30, 0x9f, 0xe5, 0x03, 0x27, 0xa0, 0xe3, 0x04, 0x21, 0x83, 0xe5, 0x02, 0x2c, 0xa0, 0xe3,
48 0x00, 0x27, 0x83, 0xe5, 0x00, 0x25, 0x83, 0xe5, 0x24, 0x20, 0x9f, 0xe5, 0x0b, 0x39, 0x83, 0xe2,
49 0x00, 0x21, 0x83, 0xe5, 0xef, 0xff, 0xff, 0xea, 0x63, 0x68, 0x72, 0x67, 0x00, 0x00, 0x05, 0x80,
50 0x00, 0xc0, 0x05, 0x80, 0x00, 0x40, 0x04, 0x80, 0x00, 0x80, 0x01, 0x80, 0x70, 0x64, 0x08, 0x00,
51 0x7f, 0x1a, 0x06, 0x00, 0x01, 0x00, 0xff, 0xff
52};
53unsigned char dualboot_zenxfi2[608] = {
54 0x10, 0x40, 0x2d, 0xe9, 0x30, 0x00, 0x00, 0xeb, 0x10, 0x80, 0xbd, 0xe8, 0x40, 0x30, 0x9f, 0xe5,
55 0xb0, 0x30, 0x93, 0xe5, 0x03, 0x18, 0xa0, 0xe1, 0x21, 0x18, 0xa0, 0xe1, 0x34, 0x20, 0x9f, 0xe5,
56 0x02, 0x00, 0x51, 0xe1, 0x08, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x50, 0xe3, 0x01, 0x38, 0x03, 0x02,
57 0x23, 0x08, 0xa0, 0x01, 0x1e, 0xff, 0x2f, 0x01, 0x01, 0x00, 0x50, 0xe3, 0x02, 0x00, 0x00, 0x1a,
58 0x06, 0x38, 0x03, 0xe2, 0xa3, 0x08, 0xa0, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0xa0, 0xe3,
59 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x04, 0x40, 0x2d, 0xe5,
60 0x5c, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x92, 0xe5, 0x03, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xa0, 0xe1,
61 0x50, 0x20, 0x9f, 0xe5, 0x02, 0x00, 0x54, 0xe1, 0x02, 0x30, 0xa0, 0x11, 0x00, 0x00, 0x50, 0xe3,
62 0x02, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe3, 0x09, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0xea,
63 0x01, 0x38, 0xc3, 0xe3, 0x01, 0x18, 0xa0, 0xe1, 0x01, 0x18, 0x01, 0xe2, 0x01, 0x30, 0x83, 0xe1,
64 0x03, 0x00, 0x00, 0xea, 0x06, 0x38, 0xc3, 0xe3, 0x81, 0x18, 0xa0, 0xe1, 0x06, 0x18, 0x01, 0xe2,
65 0x01, 0x30, 0x83, 0xe1, 0x08, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x82, 0xe5, 0x10, 0x00, 0xbd, 0xe8,
66 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x70, 0x40, 0x2d, 0xe9,
67 0x00, 0x40, 0xa0, 0xe1, 0x01, 0x60, 0xa0, 0xe1, 0x6c, 0x31, 0x9f, 0xe5, 0x03, 0x00, 0x50, 0xe1,
68 0x34, 0x00, 0x00, 0x1a, 0x64, 0x31, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5,
69 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
70 0x02, 0x21, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x0f, 0x28, 0xc2, 0xe3,
71 0x01, 0x28, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x7f, 0x2e, 0xc2, 0xe3,
72 0x0f, 0x20, 0xc2, 0xe3, 0xc8, 0x20, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0x01, 0x26, 0xa0, 0xe3,
73 0xd4, 0x20, 0x83, 0xe5, 0x34, 0x21, 0x83, 0xe5, 0x30, 0x11, 0x93, 0xe5, 0x03, 0x18, 0xc1, 0xe3,
74 0x02, 0x18, 0x81, 0xe3, 0x30, 0x11, 0x83, 0xe5, 0x03, 0x39, 0x43, 0xe2, 0x30, 0x10, 0x93, 0xe5,
75 0x0f, 0x1c, 0xc1, 0xe3, 0x01, 0x1c, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x30, 0x10, 0x93, 0xe5,
76 0x3f, 0x10, 0xc1, 0xe3, 0x10, 0x10, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x01, 0x18, 0xa0, 0xe3,
77 0x38, 0x10, 0x83, 0xe5, 0x80, 0x10, 0x93, 0xe5, 0x02, 0x15, 0x81, 0xe3, 0x80, 0x10, 0x83, 0xe5,
78 0x18, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5, 0x3f, 0x2a, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3,
79 0x10, 0x20, 0x83, 0xe5, 0x01, 0x39, 0x43, 0xe2, 0x00, 0x10, 0xa0, 0xe3, 0x20, 0x20, 0x93, 0xe5,
80 0x01, 0x2a, 0x82, 0xe3, 0x20, 0x20, 0x83, 0xe5, 0x90, 0x1f, 0x07, 0xee, 0x00, 0x00, 0xa0, 0xe1,
81 0x00, 0x00, 0xa0, 0xe1, 0xf8, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
82 0xa5, 0xff, 0xff, 0xeb, 0x01, 0x00, 0xa0, 0xe3, 0x8f, 0xff, 0xff, 0xeb, 0x00, 0x50, 0xa0, 0xe1,
83 0x01, 0x00, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0x9f, 0xff, 0xff, 0xeb, 0x01, 0x00, 0x55, 0xe3,
84 0x17, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x55, 0xe3, 0x04, 0x00, 0x00, 0x1a, 0x01, 0x27, 0xa0, 0xe3,
85 0x5c, 0x30, 0x9f, 0xe5, 0x78, 0x20, 0x83, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8,
86 0x50, 0x30, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5, 0x02, 0x02, 0x13, 0xe3, 0x04, 0x00, 0x00, 0x1a,
87 0x44, 0x30, 0x9f, 0xe5, 0x00, 0x36, 0x93, 0xe5, 0x01, 0x09, 0x13, 0xe3, 0x08, 0x00, 0x00, 0x0a,
88 0x04, 0x00, 0x00, 0xea, 0x2c, 0x30, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5, 0x03, 0x36, 0x03, 0xe2,
89 0x01, 0x06, 0x53, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x40, 0x86, 0xe5, 0x01, 0x00, 0xa0, 0xe3,
90 0x70, 0x80, 0xbd, 0xe8, 0x00, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8, 0x63, 0x68, 0x72, 0x67,
91 0x00, 0x00, 0x05, 0x80, 0x00, 0xc0, 0x05, 0x80, 0x00, 0x40, 0x04, 0x80, 0x00, 0x80, 0x01, 0x80
92};
93unsigned char dualboot_zenxfi3[572] = {
94 0x10, 0x40, 0x2d, 0xe9, 0x30, 0x00, 0x00, 0xeb, 0x10, 0x80, 0xbd, 0xe8, 0x40, 0x30, 0x9f, 0xe5,
95 0xb0, 0x30, 0x93, 0xe5, 0x03, 0x18, 0xa0, 0xe1, 0x21, 0x18, 0xa0, 0xe1, 0x34, 0x20, 0x9f, 0xe5,
96 0x02, 0x00, 0x51, 0xe1, 0x08, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x50, 0xe3, 0x01, 0x38, 0x03, 0x02,
97 0x23, 0x08, 0xa0, 0x01, 0x1e, 0xff, 0x2f, 0x01, 0x01, 0x00, 0x50, 0xe3, 0x02, 0x00, 0x00, 0x1a,
98 0x06, 0x38, 0x03, 0xe2, 0xa3, 0x08, 0xa0, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0xa0, 0xe3,
99 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x04, 0x40, 0x2d, 0xe5,
100 0x5c, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x92, 0xe5, 0x03, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xa0, 0xe1,
101 0x50, 0x20, 0x9f, 0xe5, 0x02, 0x00, 0x54, 0xe1, 0x02, 0x30, 0xa0, 0x11, 0x00, 0x00, 0x50, 0xe3,
102 0x02, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe3, 0x09, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0xea,
103 0x01, 0x38, 0xc3, 0xe3, 0x01, 0x18, 0xa0, 0xe1, 0x01, 0x18, 0x01, 0xe2, 0x01, 0x30, 0x83, 0xe1,
104 0x03, 0x00, 0x00, 0xea, 0x06, 0x38, 0xc3, 0xe3, 0x81, 0x18, 0xa0, 0xe1, 0x06, 0x18, 0x01, 0xe2,
105 0x01, 0x30, 0x83, 0xe1, 0x08, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x82, 0xe5, 0x10, 0x00, 0xbd, 0xe8,
106 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x70, 0x40, 0x2d, 0xe9,
107 0x00, 0x40, 0xa0, 0xe1, 0x01, 0x60, 0xa0, 0xe1, 0x48, 0x31, 0x9f, 0xe5, 0x03, 0x00, 0x50, 0xe1,
108 0x34, 0x00, 0x00, 0x1a, 0x40, 0x31, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5,
109 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
110 0x02, 0x21, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x0f, 0x28, 0xc2, 0xe3,
111 0x01, 0x28, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x7f, 0x2e, 0xc2, 0xe3,
112 0x0f, 0x20, 0xc2, 0xe3, 0xc8, 0x20, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0x01, 0x26, 0xa0, 0xe3,
113 0xd4, 0x20, 0x83, 0xe5, 0x34, 0x21, 0x83, 0xe5, 0x30, 0x11, 0x93, 0xe5, 0x03, 0x18, 0xc1, 0xe3,
114 0x02, 0x18, 0x81, 0xe3, 0x30, 0x11, 0x83, 0xe5, 0x03, 0x39, 0x43, 0xe2, 0x30, 0x10, 0x93, 0xe5,
115 0x0f, 0x1c, 0xc1, 0xe3, 0x01, 0x1c, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x30, 0x10, 0x93, 0xe5,
116 0x3f, 0x10, 0xc1, 0xe3, 0x10, 0x10, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x01, 0x18, 0xa0, 0xe3,
117 0x38, 0x10, 0x83, 0xe5, 0x80, 0x10, 0x93, 0xe5, 0x02, 0x15, 0x81, 0xe3, 0x80, 0x10, 0x83, 0xe5,
118 0x18, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5, 0x3f, 0x2a, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3,
119 0x10, 0x20, 0x83, 0xe5, 0x01, 0x39, 0x43, 0xe2, 0x00, 0x10, 0xa0, 0xe3, 0x20, 0x20, 0x93, 0xe5,
120 0x01, 0x2a, 0x82, 0xe3, 0x20, 0x20, 0x83, 0xe5, 0x90, 0x1f, 0x07, 0xee, 0x00, 0x00, 0xa0, 0xe1,
121 0x00, 0x00, 0xa0, 0xe1, 0xf8, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
122 0xa5, 0xff, 0xff, 0xeb, 0x01, 0x00, 0xa0, 0xe3, 0x8f, 0xff, 0xff, 0xeb, 0x00, 0x50, 0xa0, 0xe1,
123 0x01, 0x00, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0x9f, 0xff, 0xff, 0xeb, 0x01, 0x00, 0x55, 0xe3,
124 0x0e, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x55, 0xe3, 0x04, 0x00, 0x00, 0x1a, 0x01, 0x27, 0xa0, 0xe3,
125 0x38, 0x30, 0x9f, 0xe5, 0x78, 0x20, 0x83, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8,
126 0x2c, 0x30, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5, 0x28, 0x30, 0x9f, 0xe5, 0x20, 0x36, 0x93, 0xe5,
127 0x80, 0x00, 0x13, 0xe3, 0x00, 0x40, 0x86, 0x15, 0x01, 0x00, 0xa0, 0x13, 0x70, 0x80, 0xbd, 0x18,
128 0x00, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8, 0x63, 0x68, 0x72, 0x67, 0x00, 0x00, 0x05, 0x80,
129 0x00, 0xc0, 0x05, 0x80, 0x00, 0x40, 0x04, 0x80, 0x00, 0x80, 0x01, 0x80
130};
131unsigned char dualboot_nwze370[896] = {
132 0x10, 0x40, 0x2d, 0xe9, 0x48, 0x00, 0x00, 0xeb, 0x10, 0x80, 0xbd, 0xe8, 0x40, 0x30, 0x9f, 0xe5,
133 0xb0, 0x30, 0x93, 0xe5, 0x03, 0x18, 0xa0, 0xe1, 0x21, 0x18, 0xa0, 0xe1, 0x34, 0x20, 0x9f, 0xe5,
134 0x02, 0x00, 0x51, 0xe1, 0x08, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x50, 0xe3, 0x01, 0x38, 0x03, 0x02,
135 0x23, 0x08, 0xa0, 0x01, 0x1e, 0xff, 0x2f, 0x01, 0x01, 0x00, 0x50, 0xe3, 0x02, 0x00, 0x00, 0x1a,
136 0x06, 0x38, 0x03, 0xe2, 0xa3, 0x08, 0xa0, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0xa0, 0xe3,
137 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x04, 0x40, 0x2d, 0xe5,
138 0x5c, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x92, 0xe5, 0x03, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xa0, 0xe1,
139 0x50, 0x20, 0x9f, 0xe5, 0x02, 0x00, 0x54, 0xe1, 0x02, 0x30, 0xa0, 0x11, 0x00, 0x00, 0x50, 0xe3,
140 0x02, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe3, 0x09, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0xea,
141 0x01, 0x38, 0xc3, 0xe3, 0x01, 0x18, 0xa0, 0xe1, 0x01, 0x18, 0x01, 0xe2, 0x01, 0x30, 0x83, 0xe1,
142 0x03, 0x00, 0x00, 0xea, 0x06, 0x38, 0xc3, 0xe3, 0x81, 0x18, 0xa0, 0xe1, 0x06, 0x18, 0x01, 0xe2,
143 0x01, 0x30, 0x83, 0xe1, 0x08, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x82, 0xe5, 0x10, 0x00, 0xbd, 0xe8,
144 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x54, 0x30, 0x9f, 0xe5,
145 0x01, 0x20, 0xa0, 0xe3, 0x18, 0x20, 0x83, 0xe5, 0x04, 0x20, 0x83, 0xe5, 0x03, 0x20, 0xa0, 0xe1,
146 0x10, 0x30, 0x92, 0xe5, 0x01, 0x00, 0x13, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x34, 0x30, 0x9f, 0xe5,
147 0x50, 0x00, 0x93, 0xe5, 0xff, 0x04, 0xc0, 0xe3, 0x3f, 0x07, 0xc0, 0xe3, 0x41, 0x3e, 0x40, 0xe2,
148 0x0a, 0x30, 0x43, 0xe2, 0x63, 0x00, 0x53, 0xe3, 0x02, 0x00, 0xa0, 0x93, 0x1e, 0xff, 0x2f, 0x91,
149 0x16, 0x0d, 0x40, 0xe2, 0x0c, 0x00, 0x40, 0xe2, 0x63, 0x00, 0x50, 0xe3, 0x00, 0x00, 0xa0, 0x83,
150 0x01, 0x00, 0xa0, 0x93, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x05, 0x80, 0xf0, 0x41, 0x2d, 0xe9,
151 0x00, 0x60, 0xa0, 0xe1, 0x01, 0x70, 0xa0, 0xe1, 0x28, 0x32, 0x9f, 0xe5, 0x03, 0x00, 0x50, 0xe1,
152 0x34, 0x00, 0x00, 0x1a, 0x20, 0x32, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5,
153 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
154 0x02, 0x21, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x0f, 0x28, 0xc2, 0xe3,
155 0x01, 0x28, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x7f, 0x2e, 0xc2, 0xe3,
156 0x0f, 0x20, 0xc2, 0xe3, 0xc8, 0x20, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0x01, 0x26, 0xa0, 0xe3,
157 0xd4, 0x20, 0x83, 0xe5, 0x34, 0x21, 0x83, 0xe5, 0x30, 0x11, 0x93, 0xe5, 0x03, 0x18, 0xc1, 0xe3,
158 0x02, 0x18, 0x81, 0xe3, 0x30, 0x11, 0x83, 0xe5, 0x03, 0x39, 0x43, 0xe2, 0x30, 0x10, 0x93, 0xe5,
159 0x0f, 0x1c, 0xc1, 0xe3, 0x01, 0x1c, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x30, 0x10, 0x93, 0xe5,
160 0x3f, 0x10, 0xc1, 0xe3, 0x10, 0x10, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x01, 0x18, 0xa0, 0xe3,
161 0x38, 0x10, 0x83, 0xe5, 0x80, 0x10, 0x93, 0xe5, 0x02, 0x15, 0x81, 0xe3, 0x80, 0x10, 0x83, 0xe5,
162 0x18, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5, 0x3f, 0x2a, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3,
163 0x10, 0x20, 0x83, 0xe5, 0x01, 0x39, 0x43, 0xe2, 0x00, 0x10, 0xa0, 0xe3, 0x20, 0x20, 0x93, 0xe5,
164 0x01, 0x2a, 0x82, 0xe3, 0x20, 0x20, 0x83, 0xe5, 0x90, 0x1f, 0x07, 0xee, 0x00, 0x00, 0xa0, 0xe1,
165 0x00, 0x00, 0xa0, 0xe1, 0xf8, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
166 0x8d, 0xff, 0xff, 0xeb, 0x01, 0x00, 0xa0, 0xe3, 0x77, 0xff, 0xff, 0xeb, 0x00, 0x40, 0xa0, 0xe1,
167 0x01, 0x00, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0x87, 0xff, 0xff, 0xeb, 0x01, 0x00, 0x54, 0xe3,
168 0x31, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x54, 0xe3, 0x04, 0x00, 0x00, 0x1a, 0x01, 0x27, 0xa0, 0xe3,
169 0x18, 0x31, 0x9f, 0xe5, 0x78, 0x20, 0x83, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0xf0, 0x81, 0xbd, 0xe8,
170 0x0c, 0x31, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5, 0x3f, 0x34, 0x03, 0xe2, 0x23, 0x3c, 0xa0, 0xe1,
171 0x20, 0x00, 0x13, 0xe3, 0x01, 0x00, 0x00, 0x1a, 0x10, 0x00, 0x13, 0xe3, 0x24, 0x00, 0x00, 0x0a,
172 0xe4, 0x30, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5, 0x03, 0x21, 0x82, 0xe2,
173 0x08, 0x20, 0x83, 0xe5, 0x3f, 0x21, 0x82, 0xe2, 0x48, 0x21, 0x83, 0xe5, 0x00, 0x20, 0xa0, 0xe3,
174 0x44, 0x21, 0x83, 0xe5, 0x3f, 0x24, 0x82, 0xe2, 0x58, 0x20, 0x83, 0xe5, 0xc2, 0x24, 0x82, 0xe2,
175 0x24, 0x20, 0x83, 0xe5, 0x84, 0xff, 0xff, 0xeb, 0x00, 0x40, 0x50, 0xe2, 0x06, 0x00, 0x00, 0x1a,
176 0x0a, 0x00, 0x00, 0xea, 0x80, 0xff, 0xff, 0xeb, 0x00, 0x00, 0x54, 0xe1, 0x0a, 0x00, 0x00, 0x1a,
177 0xc0, 0x30, 0x98, 0xe5, 0x03, 0x00, 0x55, 0xe1, 0xf9, 0xff, 0xff, 0x8a, 0x01, 0x00, 0x54, 0xe3,
178 0x02, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x54, 0xe3, 0x03, 0x00, 0x00, 0x1a, 0x06, 0x00, 0x00, 0xea,
179 0x00, 0x60, 0x87, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0xf0, 0x81, 0xbd, 0xe8, 0x74, 0x20, 0x9f, 0xe5,
180 0x6c, 0x30, 0x9f, 0xe5, 0x00, 0x21, 0x83, 0xe5, 0xfe, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3,
181 0xf0, 0x81, 0xbd, 0xe8, 0x50, 0x30, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5,
182 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0x3f, 0x21, 0x82, 0xe2, 0x48, 0x21, 0x83, 0xe5,
183 0x00, 0x20, 0xa0, 0xe3, 0x44, 0x21, 0x83, 0xe5, 0x3f, 0x24, 0x82, 0xe2, 0x58, 0x20, 0x83, 0xe5,
184 0xc2, 0x24, 0x82, 0xe2, 0x24, 0x20, 0x83, 0xe5, 0x5f, 0xff, 0xff, 0xeb, 0x00, 0x40, 0xa0, 0xe1,
185 0x24, 0x30, 0x9f, 0xe5, 0xc0, 0x50, 0x93, 0xe5, 0x3d, 0x59, 0x85, 0xe2, 0x09, 0x5d, 0x85, 0xe2,
186 0x03, 0x80, 0xa0, 0xe1, 0xd9, 0xff, 0xff, 0xea, 0x63, 0x68, 0x72, 0x67, 0x00, 0x00, 0x05, 0x80,
187 0x00, 0xc0, 0x05, 0x80, 0x00, 0x40, 0x04, 0x80, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc0, 0x01, 0x80
188};
189unsigned char dualboot_nwze360[944] = {
190 0x10, 0x40, 0x2d, 0xe9, 0x4e, 0x00, 0x00, 0xeb, 0x10, 0x80, 0xbd, 0xe8, 0x40, 0x30, 0x9f, 0xe5,
191 0xb0, 0x30, 0x93, 0xe5, 0x03, 0x18, 0xa0, 0xe1, 0x21, 0x18, 0xa0, 0xe1, 0x34, 0x20, 0x9f, 0xe5,
192 0x02, 0x00, 0x51, 0xe1, 0x08, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x50, 0xe3, 0x01, 0x38, 0x03, 0x02,
193 0x23, 0x08, 0xa0, 0x01, 0x1e, 0xff, 0x2f, 0x01, 0x01, 0x00, 0x50, 0xe3, 0x02, 0x00, 0x00, 0x1a,
194 0x06, 0x38, 0x03, 0xe2, 0xa3, 0x08, 0xa0, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0xa0, 0xe3,
195 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x04, 0x40, 0x2d, 0xe5,
196 0x5c, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x92, 0xe5, 0x03, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xa0, 0xe1,
197 0x50, 0x20, 0x9f, 0xe5, 0x02, 0x00, 0x54, 0xe1, 0x02, 0x30, 0xa0, 0x11, 0x00, 0x00, 0x50, 0xe3,
198 0x02, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe3, 0x09, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0xea,
199 0x01, 0x38, 0xc3, 0xe3, 0x01, 0x18, 0xa0, 0xe1, 0x01, 0x18, 0x01, 0xe2, 0x01, 0x30, 0x83, 0xe1,
200 0x03, 0x00, 0x00, 0xea, 0x06, 0x38, 0xc3, 0xe3, 0x81, 0x18, 0xa0, 0xe1, 0x06, 0x18, 0x01, 0xe2,
201 0x01, 0x30, 0x83, 0xe1, 0x08, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x82, 0xe5, 0x10, 0x00, 0xbd, 0xe8,
202 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x68, 0x30, 0x9f, 0xe5,
203 0x01, 0x20, 0xa0, 0xe3, 0x18, 0x20, 0x83, 0xe5, 0x04, 0x20, 0x83, 0xe5, 0x03, 0x20, 0xa0, 0xe1,
204 0x10, 0x30, 0x92, 0xe5, 0x01, 0x00, 0x13, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x48, 0x30, 0x9f, 0xe5,
205 0x50, 0x30, 0x93, 0xe5, 0x44, 0x20, 0x9f, 0xe5, 0x00, 0x26, 0x92, 0xe5, 0x02, 0x0c, 0x12, 0xe3,
206 0x00, 0x00, 0xa0, 0x03, 0x1e, 0xff, 0x2f, 0x01, 0xff, 0x34, 0xc3, 0xe3, 0x3f, 0x37, 0xc3, 0xe3,
207 0x41, 0x2e, 0x43, 0xe2, 0x0a, 0x20, 0x42, 0xe2, 0x63, 0x00, 0x52, 0xe3, 0x02, 0x00, 0xa0, 0x93,
208 0x1e, 0xff, 0x2f, 0x91, 0x16, 0x3d, 0x43, 0xe2, 0x0c, 0x30, 0x43, 0xe2, 0x63, 0x00, 0x53, 0xe3,
209 0x00, 0x00, 0xa0, 0x83, 0x01, 0x00, 0xa0, 0x93, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0x05, 0x80,
210 0x00, 0x80, 0x01, 0x80, 0xf0, 0x41, 0x2d, 0xe9, 0x00, 0x60, 0xa0, 0xe1, 0x01, 0x70, 0xa0, 0xe1,
211 0x40, 0x32, 0x9f, 0xe5, 0x03, 0x00, 0x50, 0xe1, 0x34, 0x00, 0x00, 0x1a, 0x38, 0x32, 0x9f, 0xe5,
212 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5, 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5,
213 0xd0, 0x20, 0x93, 0xe5, 0xff, 0x24, 0xc2, 0xe3, 0x02, 0x21, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5,
214 0xd0, 0x20, 0x93, 0xe5, 0x0f, 0x28, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5,
215 0xd0, 0x20, 0x93, 0xe5, 0x7f, 0x2e, 0xc2, 0xe3, 0x0f, 0x20, 0xc2, 0xe3, 0xc8, 0x20, 0x82, 0xe3,
216 0xd0, 0x20, 0x83, 0xe5, 0x01, 0x26, 0xa0, 0xe3, 0xd4, 0x20, 0x83, 0xe5, 0x34, 0x21, 0x83, 0xe5,
217 0x30, 0x11, 0x93, 0xe5, 0x03, 0x18, 0xc1, 0xe3, 0x02, 0x18, 0x81, 0xe3, 0x30, 0x11, 0x83, 0xe5,
218 0x03, 0x39, 0x43, 0xe2, 0x30, 0x10, 0x93, 0xe5, 0x0f, 0x1c, 0xc1, 0xe3, 0x01, 0x1c, 0x81, 0xe3,
219 0x30, 0x10, 0x83, 0xe5, 0x30, 0x10, 0x93, 0xe5, 0x3f, 0x10, 0xc1, 0xe3, 0x10, 0x10, 0x81, 0xe3,
220 0x30, 0x10, 0x83, 0xe5, 0x01, 0x18, 0xa0, 0xe3, 0x38, 0x10, 0x83, 0xe5, 0x80, 0x10, 0x93, 0xe5,
221 0x02, 0x15, 0x81, 0xe3, 0x80, 0x10, 0x83, 0xe5, 0x18, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5,
222 0x3f, 0x2a, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3, 0x10, 0x20, 0x83, 0xe5, 0x01, 0x39, 0x43, 0xe2,
223 0x00, 0x10, 0xa0, 0xe3, 0x20, 0x20, 0x93, 0xe5, 0x01, 0x2a, 0x82, 0xe3, 0x20, 0x20, 0x83, 0xe5,
224 0x90, 0x1f, 0x07, 0xee, 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1, 0xf8, 0xff, 0xff, 0xea,
225 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3, 0x87, 0xff, 0xff, 0xeb, 0x01, 0x00, 0xa0, 0xe3,
226 0x71, 0xff, 0xff, 0xeb, 0x00, 0x40, 0xa0, 0xe1, 0x01, 0x00, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3,
227 0x81, 0xff, 0xff, 0xeb, 0x01, 0x00, 0x54, 0xe3, 0x34, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x54, 0xe3,
228 0x04, 0x00, 0x00, 0x1a, 0x01, 0x27, 0xa0, 0xe3, 0x30, 0x31, 0x9f, 0xe5, 0x78, 0x20, 0x83, 0xe5,
229 0x00, 0x00, 0xa0, 0xe3, 0xf0, 0x81, 0xbd, 0xe8, 0x24, 0x31, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5,
230 0x3f, 0x34, 0x03, 0xe2, 0x23, 0x3c, 0xa0, 0xe1, 0x20, 0x00, 0x13, 0xe3, 0x01, 0x00, 0x00, 0x1a,
231 0x10, 0x00, 0x13, 0xe3, 0x27, 0x00, 0x00, 0x0a, 0xfc, 0x30, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3,
232 0x08, 0x20, 0x83, 0xe5, 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0x3f, 0x21, 0x82, 0xe2,
233 0x48, 0x21, 0x83, 0xe5, 0x00, 0x20, 0xa0, 0xe3, 0x44, 0x21, 0x83, 0xe5, 0x3f, 0x24, 0x82, 0xe2,
234 0x58, 0x20, 0x83, 0xe5, 0xc2, 0x24, 0x82, 0xe2, 0x24, 0x20, 0x83, 0xe5, 0x02, 0x2c, 0xa0, 0xe3,
235 0x0e, 0x39, 0x43, 0xe2, 0x04, 0x24, 0x83, 0xe5, 0x7b, 0xff, 0xff, 0xeb, 0x00, 0x40, 0x50, 0xe2,
236 0x06, 0x00, 0x00, 0x1a, 0x0a, 0x00, 0x00, 0xea, 0x77, 0xff, 0xff, 0xeb, 0x00, 0x00, 0x54, 0xe1,
237 0x0a, 0x00, 0x00, 0x1a, 0xc0, 0x30, 0x98, 0xe5, 0x03, 0x00, 0x55, 0xe1, 0xf9, 0xff, 0xff, 0x8a,
238 0x01, 0x00, 0x54, 0xe3, 0x02, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x54, 0xe3, 0x03, 0x00, 0x00, 0x1a,
239 0x06, 0x00, 0x00, 0xea, 0x00, 0x60, 0x87, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0xf0, 0x81, 0xbd, 0xe8,
240 0x80, 0x20, 0x9f, 0xe5, 0x78, 0x30, 0x9f, 0xe5, 0x00, 0x21, 0x83, 0xe5, 0xfe, 0xff, 0xff, 0xea,
241 0x00, 0x00, 0xa0, 0xe3, 0xf0, 0x81, 0xbd, 0xe8, 0x5c, 0x30, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3,
242 0x08, 0x20, 0x83, 0xe5, 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0x3f, 0x21, 0x82, 0xe2,
243 0x48, 0x21, 0x83, 0xe5, 0x00, 0x20, 0xa0, 0xe3, 0x44, 0x21, 0x83, 0xe5, 0x3f, 0x24, 0x82, 0xe2,
244 0x58, 0x20, 0x83, 0xe5, 0xc2, 0x24, 0x82, 0xe2, 0x24, 0x20, 0x83, 0xe5, 0x02, 0x2c, 0xa0, 0xe3,
245 0x0e, 0x39, 0x43, 0xe2, 0x04, 0x24, 0x83, 0xe5, 0x53, 0xff, 0xff, 0xeb, 0x00, 0x40, 0xa0, 0xe1,
246 0x24, 0x30, 0x9f, 0xe5, 0xc0, 0x50, 0x93, 0xe5, 0x3d, 0x59, 0x85, 0xe2, 0x09, 0x5d, 0x85, 0xe2,
247 0x03, 0x80, 0xa0, 0xe1, 0xd6, 0xff, 0xff, 0xea, 0x63, 0x68, 0x72, 0x67, 0x00, 0x00, 0x05, 0x80,
248 0x00, 0xc0, 0x05, 0x80, 0x00, 0x40, 0x04, 0x80, 0x01, 0x00, 0xff, 0xff, 0x00, 0xc0, 0x01, 0x80
249};
250unsigned char dualboot_zenxfistyle[660] = {
251 0x10, 0x40, 0x2d, 0xe9, 0x30, 0x00, 0x00, 0xeb, 0x10, 0x80, 0xbd, 0xe8, 0x40, 0x30, 0x9f, 0xe5,
252 0xb0, 0x30, 0x93, 0xe5, 0x03, 0x18, 0xa0, 0xe1, 0x21, 0x18, 0xa0, 0xe1, 0x34, 0x20, 0x9f, 0xe5,
253 0x02, 0x00, 0x51, 0xe1, 0x08, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x50, 0xe3, 0x01, 0x38, 0x03, 0x02,
254 0x23, 0x08, 0xa0, 0x01, 0x1e, 0xff, 0x2f, 0x01, 0x01, 0x00, 0x50, 0xe3, 0x02, 0x00, 0x00, 0x1a,
255 0x06, 0x38, 0x03, 0xe2, 0xa3, 0x08, 0xa0, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x00, 0xa0, 0xe3,
256 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x04, 0x40, 0x2d, 0xe5,
257 0x5c, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x92, 0xe5, 0x03, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xa0, 0xe1,
258 0x50, 0x20, 0x9f, 0xe5, 0x02, 0x00, 0x54, 0xe1, 0x02, 0x30, 0xa0, 0x11, 0x00, 0x00, 0x50, 0xe3,
259 0x02, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe3, 0x09, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0xea,
260 0x01, 0x38, 0xc3, 0xe3, 0x01, 0x18, 0xa0, 0xe1, 0x01, 0x18, 0x01, 0xe2, 0x01, 0x30, 0x83, 0xe1,
261 0x03, 0x00, 0x00, 0xea, 0x06, 0x38, 0xc3, 0xe3, 0x81, 0x18, 0xa0, 0xe1, 0x06, 0x18, 0x01, 0xe2,
262 0x01, 0x30, 0x83, 0xe1, 0x08, 0x20, 0x9f, 0xe5, 0xb0, 0x30, 0x82, 0xe5, 0x10, 0x00, 0xbd, 0xe8,
263 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xc0, 0x05, 0x80, 0x52, 0x42, 0x00, 0x00, 0x70, 0x40, 0x2d, 0xe9,
264 0x00, 0x40, 0xa0, 0xe1, 0x01, 0x60, 0xa0, 0xe1, 0xa4, 0x31, 0x9f, 0xe5, 0x03, 0x00, 0x50, 0xe1,
265 0x34, 0x00, 0x00, 0x1a, 0x9c, 0x31, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3, 0x08, 0x20, 0x83, 0xe5,
266 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
267 0x02, 0x21, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x0f, 0x28, 0xc2, 0xe3,
268 0x01, 0x28, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0xd0, 0x20, 0x93, 0xe5, 0x7f, 0x2e, 0xc2, 0xe3,
269 0x0f, 0x20, 0xc2, 0xe3, 0xc8, 0x20, 0x82, 0xe3, 0xd0, 0x20, 0x83, 0xe5, 0x01, 0x26, 0xa0, 0xe3,
270 0xd4, 0x20, 0x83, 0xe5, 0x34, 0x21, 0x83, 0xe5, 0x30, 0x11, 0x93, 0xe5, 0x03, 0x18, 0xc1, 0xe3,
271 0x02, 0x18, 0x81, 0xe3, 0x30, 0x11, 0x83, 0xe5, 0x03, 0x39, 0x43, 0xe2, 0x30, 0x10, 0x93, 0xe5,
272 0x0f, 0x1c, 0xc1, 0xe3, 0x01, 0x1c, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x30, 0x10, 0x93, 0xe5,
273 0x3f, 0x10, 0xc1, 0xe3, 0x10, 0x10, 0x81, 0xe3, 0x30, 0x10, 0x83, 0xe5, 0x01, 0x18, 0xa0, 0xe3,
274 0x38, 0x10, 0x83, 0xe5, 0x80, 0x10, 0x93, 0xe5, 0x02, 0x15, 0x81, 0xe3, 0x80, 0x10, 0x83, 0xe5,
275 0x18, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5, 0x3f, 0x2a, 0xc2, 0xe3, 0x01, 0x28, 0x82, 0xe3,
276 0x10, 0x20, 0x83, 0xe5, 0x01, 0x39, 0x43, 0xe2, 0x00, 0x10, 0xa0, 0xe3, 0x20, 0x20, 0x93, 0xe5,
277 0x01, 0x2a, 0x82, 0xe3, 0x20, 0x20, 0x83, 0xe5, 0x90, 0x1f, 0x07, 0xee, 0x00, 0x00, 0xa0, 0xe1,
278 0x00, 0x00, 0xa0, 0xe1, 0xf8, 0xff, 0xff, 0xea, 0x00, 0x00, 0xa0, 0xe3, 0x01, 0x10, 0xa0, 0xe3,
279 0xa5, 0xff, 0xff, 0xeb, 0x01, 0x00, 0xa0, 0xe3, 0x8f, 0xff, 0xff, 0xeb, 0x00, 0x50, 0xa0, 0xe1,
280 0x01, 0x00, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0x9f, 0xff, 0xff, 0xeb, 0x01, 0x00, 0x55, 0xe3,
281 0x25, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x55, 0xe3, 0x04, 0x00, 0x00, 0x1a, 0x01, 0x27, 0xa0, 0xe3,
282 0x94, 0x30, 0x9f, 0xe5, 0x78, 0x20, 0x83, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0x70, 0x80, 0xbd, 0xe8,
283 0x88, 0x30, 0x9f, 0xe5, 0xc0, 0x30, 0x93, 0xe5, 0x78, 0x30, 0x9f, 0xe5, 0x02, 0x21, 0xa0, 0xe3,
284 0x08, 0x20, 0x83, 0xe5, 0x03, 0x21, 0x82, 0xe2, 0x08, 0x20, 0x83, 0xe5, 0x0f, 0x2c, 0xa0, 0xe3,
285 0x48, 0x21, 0x83, 0xe5, 0x0d, 0x2c, 0x42, 0xe2, 0x44, 0x21, 0x83, 0xe5, 0x3f, 0x24, 0xa0, 0xe3,
286 0x78, 0x20, 0x83, 0xe5, 0xc5, 0x24, 0x82, 0xe2, 0x24, 0x20, 0x83, 0xe5, 0x04, 0x20, 0xa0, 0xe3,
287 0x18, 0x20, 0x83, 0xe5, 0x04, 0x20, 0x83, 0xe5, 0x10, 0x20, 0x93, 0xe5, 0x04, 0x00, 0x12, 0xe3,
288 0xfc, 0xff, 0xff, 0x0a, 0x2c, 0x30, 0x9f, 0xe5, 0x70, 0x30, 0x93, 0xe5, 0xff, 0x34, 0xc3, 0xe3,
289 0x3f, 0x37, 0xc3, 0xe3, 0xcb, 0x3f, 0x43, 0xe2, 0x03, 0x30, 0x43, 0xe2, 0x63, 0x00, 0x53, 0xe3,
290 0x00, 0x40, 0x86, 0x85, 0x01, 0x00, 0xa0, 0x83, 0x70, 0x80, 0xbd, 0x88, 0x00, 0x00, 0xa0, 0xe3,
291 0x70, 0x80, 0xbd, 0xe8, 0x63, 0x68, 0x72, 0x67, 0x00, 0x00, 0x05, 0x80, 0x00, 0xc0, 0x05, 0x80,
292 0x00, 0x40, 0x04, 0x80
293};
diff --git a/utils/mkimxboot/dualboot.h b/utils/mkimxboot/dualboot.h
new file mode 100644
index 0000000000..fbce031d56
--- /dev/null
+++ b/utils/mkimxboot/dualboot.h
@@ -0,0 +1,8 @@
1/* Generated by bin2c */
2
3extern unsigned char dualboot_fuzeplus[728];
4extern unsigned char dualboot_zenxfi2[608];
5extern unsigned char dualboot_zenxfi3[572];
6extern unsigned char dualboot_nwze370[896];
7extern unsigned char dualboot_nwze360[944];
8extern unsigned char dualboot_zenxfistyle[660];
diff --git a/utils/mkimxboot/dualboot/Makefile b/utils/mkimxboot/dualboot/Makefile
new file mode 100644
index 0000000000..b80233226a
--- /dev/null
+++ b/utils/mkimxboot/dualboot/Makefile
@@ -0,0 +1,48 @@
1CC=gcc
2LD=ld
3OC=objcopy
4PREFIX?=arm-elf-eabi-
5IMX233_PATH=../../../firmware/target/arm/imx233
6CFLAGS=-mcpu=arm926ej-s -std=gnu99 -I. -I$(IMX233_PATH) -nostdlib -ffreestanding -fomit-frame-pointer -O
7# Edit the following variables when adding a new target.
8# mkimxboot.c also needs to be edited to refer to these
9# To add a new target x you need to:
10# 1) add x to the list in TARGETS
11# 2) create a variable named OPT_x of the form:
12# OPT_x=target specific defines
13TARGETS=fuzeplus zenxfi2 zenxfi3 nwze370 nwze360 zenxfistyle
14OPT_fuzeplus=-DSANSA_FUZEPLUS -DIMX233_SUBTARGET=3780
15OPT_zenxfi2=-DCREATIVE_ZENXFI2 -DIMX233_SUBTARGET=3780
16OPT_zenxfi3=-DCREATIVE_ZENXFI3 -DIMX233_SUBTARGET=3780
17OPT_nwze370=-DSONY_NWZE370 -DIMX233_SUBTARGET=3780
18OPT_nwze360=-DSONY_NWZE360 -DIMX233_SUBTARGET=3780
19OPT_zenxfistyle=-DCREATIVE_ZENXFISTYLE -DIMX233_SUBTARGET=3780
20
21BOOTOBJS=$(patsubst %, dualboot_%.o, $(TARGETS))
22BOOTBINS=$(patsubst %, dualboot_%.arm-bin, $(TARGETS))
23BOOTELFS=$(patsubst %, dualboot_%.arm-elf, $(TARGETS))
24
25all: ../dualboot.h ../dualboot.c $(BOOTELFS)
26
27# Dualboot bootloaders
28
29dualboot_%.o: dualboot.c
30 $(PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.o=%)) -c -o $@ $^
31
32dualboot_%.arm-elf: dualboot_%.o
33 $(PREFIX)$(LD) $(LDFLAGS) -Tdualboot.lds -o $@ $<
34
35# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
36# the binary code and finally convert to .h for building in mkamsboot
37
38%.arm-bin: %.arm-elf
39 $(PREFIX)$(OC) -O binary $< $@
40
41../dualboot.c ../dualboot.h: $(BOOTBINS) bin2c
42 ./bin2c ../dualboot $(BOOTBINS)
43
44bin2c: bin2c.c
45 $(CC) -o bin2c bin2c.c
46
47clean:
48 rm -f *~ bin2c $(BOOTBINS) $(BOOTOBJS) $(BOOTELFS)
diff --git a/utils/mkimxboot/dualboot/bin2c.c b/utils/mkimxboot/dualboot/bin2c.c
new file mode 100644
index 0000000000..b02af88a4d
--- /dev/null
+++ b/utils/mkimxboot/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
35static off_t filesize(int fd)
36{
37 struct stat buf;
38
39 fstat(fd,&buf);
40 return buf.st_size;
41}
42
43static 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
64int 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/mkimxboot/dualboot/config.h b/utils/mkimxboot/dualboot/config.h
new file mode 100644
index 0000000000..e9ea8d4a35
--- /dev/null
+++ b/utils/mkimxboot/dualboot/config.h
@@ -0,0 +1,26 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
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/** mostly empty, used by register files and dualboot */
23#define COMPILE_DUALBOOT_STUB
24
25/* obviously we have the dualboot stub! */
26#define HAVE_DUALBOOT_STUB
diff --git a/utils/mkimxboot/dualboot/dualboot.c b/utils/mkimxboot/dualboot/dualboot.c
new file mode 100644
index 0000000000..77b816bf76
--- /dev/null
+++ b/utils/mkimxboot/dualboot/dualboot.c
@@ -0,0 +1,323 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 by Amaury Pouly
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 "regs/pinctrl.h"
22#include "regs/power.h"
23#include "regs/lradc.h"
24#include "regs/digctl.h"
25#include "regs/clkctrl.h"
26
27#define BOOT_ROM_CONTINUE 0 /* continue boot */
28#define BOOT_ROM_SECTION 1 /* switch to new section *result_id */
29
30#define BOOT_ARG_CHARGE ('c' | 'h' << 8 | 'r' << 16 | 'g' << 24)
31/** additional defines */
32#define BP_LRADC_CTRL4_LRADCxSELECT(x) (4 * (x))
33#define BM_LRADC_CTRL4_LRADCxSELECT(x) (0xf << (4 * (x)))
34
35typedef unsigned long uint32_t;
36
37/* we include the dualboot rtc code directly */
38#include "dualboot-imx233.h"
39#include "dualboot-imx233.c"
40
41// target specific boot context
42enum context_t
43{
44 CONTEXT_NORMAL, /* normal boot */
45 CONTEXT_USB, /* USB plugged boot */
46 CONTEXT_RTC, /* RTC wake up boot */
47};
48// target specific boot decision
49enum boot_t
50{
51 BOOT_STOP, /* power down */
52 BOOT_ROCK, /* boot to Rockbox */
53 BOOT_OF, /* boot to OF */
54};
55
56/**
57 * Helper functions
58 */
59
60static inline int __attribute__((always_inline)) read_gpio(int bank, int pin)
61{
62 return (HW_PINCTRL_DINn(bank) >> pin) & 1;
63}
64
65static inline int __attribute__((always_inline)) read_pswitch(void)
66{
67#if IMX233_SUBTARGET >= 3700
68 return BF_RD(POWER_STS, PSWITCH);
69#else
70 return BF_RD(DIGCTL_STATUS, PSWITCH);
71#endif
72}
73
74/* only works for channels <=7, always divide by 2, never accumulates */
75static inline void __attribute__((always_inline)) setup_lradc(int src)
76{
77 BF_CLR(LRADC_CTRL0, SFTRST);
78 BF_CLR(LRADC_CTRL0, CLKGATE);
79#if IMX233_SUBTARGET >= 3700
80 HW_LRADC_CTRL4_CLR = BM_LRADC_CTRL4_LRADCxSELECT(src);
81 HW_LRADC_CTRL4_SET = src << BP_LRADC_CTRL4_LRADCxSELECT(src);
82#endif
83 HW_LRADC_CHn_CLR(src) = BM_OR(LRADC_CHn, NUM_SAMPLES, ACCUMULATE);
84 BF_WR(LRADC_CTRL2_SET, DIVIDE_BY_TWO(1 << src));
85}
86
87#define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x)
88#define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x))
89
90static inline int __attribute__((always_inline)) read_lradc(int src)
91{
92 BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src));
93 BF_WR(LRADC_CTRL0_SET, SCHEDULE(1 << src));
94 while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src)));
95 return BF_RD(LRADC_CHn(src), VALUE);
96}
97
98static inline void __attribute__((noreturn)) power_down()
99{
100#ifdef SANSA_FUZEPLUS
101 /* B0P09: this pin seems to be important to shutdown the hardware properly */
102 HW_PINCTRL_MUXSELn_SET(0) = 3 << 18;
103 HW_PINCTRL_DOEn(0) = 1 << 9;
104 HW_PINCTRL_DOUTn(0) = 1 << 9;
105#endif
106 /* power down */
107 HW_POWER_RESET = BM_OR(POWER_RESET, UNLOCK, PWD);
108 while(1);
109}
110
111/**
112 * Boot decision functions
113 */
114
115#if defined(SANSA_FUZEPLUS)
116static enum boot_t boot_decision(enum context_t context)
117{
118 /* if volume down is hold, boot to OF */
119 if(!read_gpio(1, 30))
120 return BOOT_OF;
121 /* on normal boot, make sure power button is hold long enough */
122 if(context == CONTEXT_NORMAL)
123 {
124 // monitor PSWITCH
125 int count = 0;
126 for(int i = 0; i < 550000; i++)
127 if(read_pswitch() == 1)
128 count++;
129 if(count < 400000)
130 return BOOT_STOP;
131 }
132 return BOOT_ROCK;
133}
134#elif defined(CREATIVE_ZENXFI2)
135static int boot_decision(int context)
136{
137 /* We are lacking buttons on the Zen X-Fi2 because on USB, the select button
138 * enters recovery mode ! So we can only use power but power is used to power up
139 * on normal boots and then select is free ! Thus use a non-uniform scheme:
140 * - normal boot/RTC:
141 * - no key: Rockbox
142 * - select: OF
143 * - USB boot:
144 * - no key: Rockbox
145 * - power: OF
146 */
147 if(context == CONTEXT_USB)
148 return read_pswitch() == 1 ? BOOT_OF : BOOT_ROCK;
149 else
150 return !read_gpio(0, 14) ? BOOT_OF : BOOT_ROCK;
151}
152#elif defined(CREATIVE_ZENXFI3)
153static int boot_decision(int context)
154{
155 /* if volume down is hold, boot to OF */
156 return !read_gpio(2, 7) ? BOOT_OF : BOOT_ROCK;
157}
158#elif defined(SONY_NWZE360) || defined(SONY_NWZE370)
159static int local_decision(void)
160{
161 /* read keys and pswitch */
162 int val = read_lradc(0);
163 /* if hold is on, power off
164 * if back is pressed, boot to OF
165 * if play is pressed, boot RB
166 * otherwise power off */
167#ifdef SONY_NWZE360
168 if(read_gpio(0, 9) == 0)
169 return BOOT_STOP;
170#endif
171 if(val >= 1050 && val < 1150)
172 return BOOT_OF;
173 if(val >= 1420 && val < 1520)
174 return BOOT_ROCK;
175 return BOOT_STOP;
176}
177
178static int boot_decision(int context)
179{
180 setup_lradc(0); // setup LRADC channel 0 to read keys
181#ifdef SONY_NWZE360
182 HW_PINCTRL_PULLn_SET(0) = 1 << 9; // enable pullup on hold key (B0P09)
183#endif
184 /* make a decision */
185 int decision = local_decision();
186 /* in USB or alarm context, stick to it */
187 if(context == CONTEXT_USB || context == CONTEXT_RTC)
188 {
189 /* never power down so replace power off decision by rockbox */
190 return decision == BOOT_STOP ? BOOT_ROCK : decision;
191 }
192 /* otherwise start a 1 second timeout. Any decision change
193 * will result in power down */
194 uint32_t tmo = HW_DIGCTL_MICROSECONDS + 1000000;
195 while(HW_DIGCTL_MICROSECONDS < tmo)
196 {
197 int new_dec = local_decision();
198 if(new_dec != decision)
199 return BOOT_STOP;
200 }
201 return decision;
202}
203#elif defined(CREATIVE_ZENXFISTYLE)
204static int boot_decision(int context)
205{
206 setup_lradc(2); // setup LRADC channel 2 to read keys
207 /* make a decision */
208 int val = read_lradc(2);
209 /* boot to OF if left is hold
210 * NOTE: VDDIO is set to 3.1V initially and the resistor ladder is wired to
211 * VDDIO so these values are not the same as in the main binary which is
212 * calibrated for VDDIO=3.3V */
213 if(val >= 815 && val < 915)
214 return BOOT_OF;
215 return BOOT_ROCK;
216}
217#else
218#warning You should define a target specific boot decision function
219static int boot_decision(int context)
220{
221 return BOOT_ROCK;
222}
223#endif
224
225/**
226 * Context functions
227 */
228static inline enum context_t get_context(void)
229{
230#if IMX233_SUBTARGET >= 3780
231 /* On the imx233 it's easy because we know the power up source */
232 unsigned pwrup_src = BF_RD(POWER_STS, PWRUP_SOURCE);
233 if(pwrup_src & (1 << 5))
234 return CONTEXT_USB;
235 else if(pwrup_src & (1 << 4))
236 return CONTEXT_RTC;
237 else
238 return CONTEXT_NORMAL;
239#else
240 /* On the other targets, we need to poke a few more registers */
241#endif
242}
243
244/**
245 * Charging function
246 */
247static inline void do_charge(void)
248{
249 BF_CLR(LRADC_CTRL0, SFTRST);
250 BF_CLR(LRADC_CTRL0, CLKGATE);
251 BF_WR(LRADC_DELAYn(0), TRIGGER_LRADCS(0x80));
252 BF_WR(LRADC_DELAYn(0), TRIGGER_DELAYS(0x1));
253 BF_WR(LRADC_DELAYn(0), DELAY(200));
254 BF_SET(LRADC_DELAYn(0), KICK);
255 BF_SET(LRADC_CONVERSION, AUTOMATIC);
256 BF_WR(LRADC_CONVERSION, SCALE_FACTOR_V(LI_ION));
257 BF_WR(POWER_CHARGE, STOP_ILIMIT(1));
258 BF_WR(POWER_CHARGE, BATTCHRG_I(0x10));
259 BF_CLR(POWER_CHARGE, PWD_BATTCHRG);
260#if IMX233_SUBTARGET >= 3780
261 BF_WR(POWER_DCDC4P2, ENABLE_4P2(1));
262 BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2);
263 BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(0x10));
264#endif
265 while(1)
266 {
267 BF_WR(CLKCTRL_CPU, INTERRUPT_WAIT(1));
268 asm volatile (
269 "mcr p15, 0, %0, c7, c0, 4 \n" /* Wait for interrupt */
270 "nop\n" /* Datasheet unclear: "The lr sent to handler points here after RTI"*/
271 "nop\n"
272 : : "r"(0)
273 );
274 }
275}
276
277static void set_updater_bits(void)
278{
279 /* The OF will continue to updater if we clear 18 of PERSISTENT1.
280 * See dualboot-imx233.c in firmware/ for more explanation */
281 HW_RTC_PERSISTENT1_CLR = 1 << 18;
282}
283
284int main(uint32_t arg, uint32_t *result_id)
285{
286 if(arg == BOOT_ARG_CHARGE)
287 do_charge();
288 /* tell rockbox that we can handle boot mode */
289 imx233_dualboot_set_field(DUALBOOT_CAP_BOOT, 1);
290 /* if we were asked to boot in a special mode, do so */
291 unsigned boot_mode = imx233_dualboot_get_field(DUALBOOT_BOOT);
292 /* clear boot mode to avoid any loop */
293 imx233_dualboot_set_field(DUALBOOT_BOOT, IMX233_BOOT_NORMAL);
294 switch(boot_mode)
295 {
296 case IMX233_BOOT_UPDATER:
297 set_updater_bits();
298 /* fallthrough */
299 case IMX233_BOOT_OF:
300 /* continue booting */
301 return BOOT_ROM_CONTINUE;
302 case IMX233_BOOT_NORMAL:
303 default:
304 break;
305 }
306 /* normal boot */
307 switch(boot_decision(get_context()))
308 {
309 case BOOT_ROCK:
310 *result_id = arg;
311 return BOOT_ROM_SECTION;
312 case BOOT_OF:
313 return BOOT_ROM_CONTINUE;
314 case BOOT_STOP:
315 default:
316 power_down();
317 }
318}
319
320int __attribute__((section(".start"))) start(uint32_t arg, uint32_t *result_id)
321{
322 return main(arg, result_id);
323}
diff --git a/utils/mkimxboot/dualboot/dualboot.lds b/utils/mkimxboot/dualboot/dualboot.lds
new file mode 100644
index 0000000000..09739aee15
--- /dev/null
+++ b/utils/mkimxboot/dualboot/dualboot.lds
@@ -0,0 +1,17 @@
1ENTRY(start)
2OUTPUT_FORMAT(elf32-littlearm)
3OUTPUT_ARCH(arm)
4
5MEMORY
6{
7 OCRAM : ORIGIN = 0, LENGTH = 0x8000
8}
9
10SECTIONS
11{
12 .text 0 :
13 {
14 *(.start*)
15 *(.text*)
16 } > OCRAM
17}
diff --git a/utils/mkimxboot/main.c b/utils/mkimxboot/main.c
new file mode 100644
index 0000000000..5b8cceb044
--- /dev/null
+++ b/utils/mkimxboot/main.c
@@ -0,0 +1,289 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
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 <getopt.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include "mkimxboot.h"
27
28struct imx_variant_t
29{
30 const char *name;
31 enum imx_firmware_variant_t variant;
32};
33
34static struct imx_variant_t imx_variants[] =
35{
36 { "default", VARIANT_DEFAULT },
37 { "zenxfi2-recovery", VARIANT_ZENXFI2_RECOVERY },
38 { "zenxfi2-nand", VARIANT_ZENXFI2_NAND },
39 { "zenxfi2-sd", VARIANT_ZENXFI2_SD },
40 { "zenxfistyle-recovery", VARIANT_ZENXFISTYLE_RECOVERY },
41 { "zenstyle-recovery", VARIANT_ZENSTYLE_RECOVERY },
42};
43
44#define NR_VARIANTS sizeof(imx_variants) / sizeof(imx_variants[0])
45
46struct model_t
47{
48 const char *name;
49 enum imx_model_t model;
50};
51
52struct model_t imx_models[] =
53{
54 { "unknown", MODEL_UNKNOWN },
55 { "fuzeplus", MODEL_FUZEPLUS },
56 { "zenxfi2", MODEL_ZENXFI2 },
57 { "zenxfi3", MODEL_ZENXFI3 },
58 { "zenxfistyle", MODEL_ZENXFISTYLE },
59 { "zenstyle", MODEL_ZENSTYLE },
60 { "nwze370", MODEL_NWZE370 },
61 { "nwze360", MODEL_NWZE360 },
62};
63
64#define NR_MODELS sizeof(imx_models) / sizeof(imx_models[0])
65
66static void usage(void)
67{
68 printf("Usage: mkimxboot [options | file]...\n");
69 printf("Options:\n");
70 printf(" -?/--help Display this message\n");
71 printf(" -o <file> Set output file\n");
72 printf(" -i <file> Set input file\n");
73 printf(" -b <file> Set boot file\n");
74 printf(" -d/--debug Enable debug output\n");
75 printf(" -t <type> Set type (dualboot, singleboot, recovery, origfw, charge)\n");
76 printf(" -v <v> Set variant\n");
77 printf(" -x Dump device informations\n");
78 printf(" -p <ver> Force product and component version\n");
79 printf(" -5 <type> Compute <type> MD5 sum of the input file\n");
80 printf(" -m <model> Specify model (useful for soft MD5 sum)\n");
81 printf("Supported variants: (default is standard)\n");
82 printf(" ");
83 for(size_t i = 0; i < NR_VARIANTS; i++)
84 {
85 if(i != 0)
86 printf(", ");
87 printf("%s", imx_variants[i].name);
88 }
89 printf("\n");
90 printf("Supported models: (default is unknown)\n");
91 for(size_t i = 0; i < NR_MODELS; i++)
92 {
93 if(i != 0)
94 printf(", ");
95 printf("%s", imx_models[i].name);
96 }
97 printf("\n");
98 printf("By default a dualboot image is built\n");
99 printf("This tools supports the following format for the boot file:\n");
100 printf("- rockbox scramble format\n");
101 printf("- elf format\n");
102 printf("Additional checks will be performed on rockbox scramble format to\n");
103 printf("ensure soundness of operation.\n");
104 printf("There are two types of MD5 sums: 'full' or 'soft'.\n");
105 printf("- full MD5 sum applies to the whole file\n");
106 printf("- soft MD5 sum for SB files accounts for relevant parts only\n");
107 exit(1);
108}
109
110static int print_md5(const char *file, const char *type)
111{
112 uint8_t md5sum[16];
113 enum imx_error_t err;
114 if(strcmp(type, "full") == 0)
115 err = compute_md5sum(file, md5sum);
116 else if(strcmp(type, "soft") == 0)
117 err = compute_soft_md5sum(file, md5sum);
118 else
119 {
120 printf("Invalid md5sum type '%s'\n", type);
121 return 1;
122 }
123 if(err != IMX_SUCCESS)
124 {
125 printf("There was an error when computing the MD5 sum: %d\n", err);
126 return 2;
127 }
128 printf("%s MD5 sum: ", type);
129 for(int i = 0; i < 16; i++)
130 printf("%02x", md5sum[i]);
131 printf("\n");
132 return 0;
133}
134
135int main(int argc, char *argv[])
136{
137 char *infile = NULL;
138 char *outfile = NULL;
139 char *bootfile = NULL;
140 enum imx_firmware_variant_t variant = VARIANT_DEFAULT;
141 enum imx_output_type_t type = IMX_DUALBOOT;
142 enum imx_model_t model = MODEL_UNKNOWN;
143 bool debug = false;
144 const char *md5type = NULL;
145 const char *force_version = NULL;
146
147 if(argc == 1)
148 usage();
149
150 while(1)
151 {
152 static struct option long_options[] =
153 {
154 {"help", no_argument, 0, 'h'},
155 {"in-file", no_argument, 0, 'i'},
156 {"out-file", required_argument, 0, 'o'},
157 {"boot-file", required_argument, 0, 'b'},
158 {"debug", no_argument, 0, 'd'},
159 {"type", required_argument, 0, 't'},
160 {"variant", required_argument, 0, 'v'},
161 {"dev-info", no_argument, 0, 'x'},
162 {"model", required_argument, 0, 'm'},
163 {"md5", required_argument, 0, '5'},
164 {0, 0, 0, 0}
165 };
166
167 int c = getopt_long(argc, argv, "hdi:o:b:t:v:xp:m:5:", long_options, NULL);
168 if(c == -1)
169 break;
170 switch(c)
171 {
172 case 'd':
173 debug = true;
174 break;
175 case 'h':
176 usage();
177 break;
178 case 'o':
179 outfile = optarg;
180 break;
181 case 'i':
182 infile = optarg;
183 break;
184 case 'b':
185 bootfile = optarg;
186 break;
187 case 't':
188 if(strcmp(optarg, "dualboot") == 0)
189 type = IMX_DUALBOOT;
190 else if(strcmp(optarg, "singleboot") == 0)
191 type = IMX_SINGLEBOOT;
192 else if(strcmp(optarg, "recovery") == 0)
193 type = IMX_RECOVERY;
194 else if(strcmp(optarg, "charge") == 0)
195 type = IMX_CHARGE;
196 else if(strcmp(optarg, "origfw") == 0)
197 type = IMX_ORIG_FW;
198 else
199 {
200 printf("Invalid boot type '%s'\n", optarg);
201 return 1;
202 }
203 break;
204 case 'v':
205 {
206 for(size_t i = 0; i < NR_VARIANTS; i++)
207 {
208 if(strcmp(optarg, imx_variants[i].name) == 0)
209 {
210 variant = imx_variants[i].variant;
211 goto Lok;
212 }
213 }
214 printf("Invalid variant '%s'\n", optarg);
215 return 1;
216
217 Lok:
218 break;
219 }
220 case 'x':
221 dump_imx_dev_info("");
222 printf("variant mapping:\n");
223 for(int i = 0; i < sizeof(imx_variants) / sizeof(imx_variants[0]); i++)
224 printf(" %s -> variant=%d\n", imx_variants[i].name, imx_variants[i].variant);
225 break;
226 case 'p':
227 force_version = optarg;
228 break;
229 case '5':
230 md5type = optarg;
231 break;
232 case 'm':
233 if(model != MODEL_UNKNOWN)
234 {
235 printf("You cannot specify two models\n");
236 return 1;
237 }
238 for(int i = 0; i < NR_MODELS; i++)
239 if(strcmp(optarg, imx_models[i].name) == 0)
240 {
241 model = imx_models[i].model;
242 break;
243 }
244 if(model == MODEL_UNKNOWN)
245 printf("Unknown model '%s'\n", optarg);
246 break;
247 default:
248 abort();
249 }
250 }
251
252 if(!infile)
253 {
254 printf("You must specify an input file\n");
255 return 1;
256 }
257
258 if(md5type)
259 return print_md5(infile, md5type);
260
261 if(!outfile)
262 {
263 printf("You must specify an output file\n");
264 return 1;
265 }
266
267 if(!bootfile && type != IMX_ORIG_FW)
268 {
269 printf("You must specify an boot file\n");
270 return 1;
271 }
272
273 if(optind != argc)
274 {
275 printf("Extra arguments on command line\n");
276 return 1;
277 }
278
279 struct imx_option_t opt;
280 memset(&opt, 0, sizeof(opt));
281 opt.debug = debug;
282 opt.output = type;
283 opt.fw_variant = variant;
284 opt.force_version = force_version;
285 opt.model = model;
286 enum imx_error_t err = mkimxboot(infile, bootfile, outfile, opt);
287 printf("Result: %d (%s)\n", err, imx_error_to_string(err));
288 return 0;
289}
diff --git a/utils/mkimxboot/md5.c b/utils/mkimxboot/md5.c
new file mode 100644
index 0000000000..530d8df15a
--- /dev/null
+++ b/utils/mkimxboot/md5.c
@@ -0,0 +1,246 @@
1/*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2001-2003 Christophe Devine
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <string.h>
22
23#include "md5.h"
24
25#define GET_UINT32(n,b,i) \
26{ \
27 (n) = ( (uint32) (b)[(i) ] ) \
28 | ( (uint32) (b)[(i) + 1] << 8 ) \
29 | ( (uint32) (b)[(i) + 2] << 16 ) \
30 | ( (uint32) (b)[(i) + 3] << 24 ); \
31}
32
33#define PUT_UINT32(n,b,i) \
34{ \
35 (b)[(i) ] = (uint8) ( (n) ); \
36 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
37 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
38 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
39}
40
41void md5_starts( md5_context *ctx )
42{
43 ctx->total[0] = 0;
44 ctx->total[1] = 0;
45
46 ctx->state[0] = 0x67452301;
47 ctx->state[1] = 0xEFCDAB89;
48 ctx->state[2] = 0x98BADCFE;
49 ctx->state[3] = 0x10325476;
50}
51
52void md5_process( md5_context *ctx, uint8 data[64] )
53{
54 uint32 X[16], A, B, C, D;
55
56 GET_UINT32( X[0], data, 0 );
57 GET_UINT32( X[1], data, 4 );
58 GET_UINT32( X[2], data, 8 );
59 GET_UINT32( X[3], data, 12 );
60 GET_UINT32( X[4], data, 16 );
61 GET_UINT32( X[5], data, 20 );
62 GET_UINT32( X[6], data, 24 );
63 GET_UINT32( X[7], data, 28 );
64 GET_UINT32( X[8], data, 32 );
65 GET_UINT32( X[9], data, 36 );
66 GET_UINT32( X[10], data, 40 );
67 GET_UINT32( X[11], data, 44 );
68 GET_UINT32( X[12], data, 48 );
69 GET_UINT32( X[13], data, 52 );
70 GET_UINT32( X[14], data, 56 );
71 GET_UINT32( X[15], data, 60 );
72
73#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
74
75#define P(a,b,c,d,k,s,t) \
76{ \
77 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
78}
79
80 A = ctx->state[0];
81 B = ctx->state[1];
82 C = ctx->state[2];
83 D = ctx->state[3];
84
85#define F(x,y,z) (z ^ (x & (y ^ z)))
86
87 P( A, B, C, D, 0, 7, 0xD76AA478 );
88 P( D, A, B, C, 1, 12, 0xE8C7B756 );
89 P( C, D, A, B, 2, 17, 0x242070DB );
90 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
91 P( A, B, C, D, 4, 7, 0xF57C0FAF );
92 P( D, A, B, C, 5, 12, 0x4787C62A );
93 P( C, D, A, B, 6, 17, 0xA8304613 );
94 P( B, C, D, A, 7, 22, 0xFD469501 );
95 P( A, B, C, D, 8, 7, 0x698098D8 );
96 P( D, A, B, C, 9, 12, 0x8B44F7AF );
97 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
98 P( B, C, D, A, 11, 22, 0x895CD7BE );
99 P( A, B, C, D, 12, 7, 0x6B901122 );
100 P( D, A, B, C, 13, 12, 0xFD987193 );
101 P( C, D, A, B, 14, 17, 0xA679438E );
102 P( B, C, D, A, 15, 22, 0x49B40821 );
103
104#undef F
105
106#define F(x,y,z) (y ^ (z & (x ^ y)))
107
108 P( A, B, C, D, 1, 5, 0xF61E2562 );
109 P( D, A, B, C, 6, 9, 0xC040B340 );
110 P( C, D, A, B, 11, 14, 0x265E5A51 );
111 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
112 P( A, B, C, D, 5, 5, 0xD62F105D );
113 P( D, A, B, C, 10, 9, 0x02441453 );
114 P( C, D, A, B, 15, 14, 0xD8A1E681 );
115 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
116 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
117 P( D, A, B, C, 14, 9, 0xC33707D6 );
118 P( C, D, A, B, 3, 14, 0xF4D50D87 );
119 P( B, C, D, A, 8, 20, 0x455A14ED );
120 P( A, B, C, D, 13, 5, 0xA9E3E905 );
121 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
122 P( C, D, A, B, 7, 14, 0x676F02D9 );
123 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
124
125#undef F
126
127#define F(x,y,z) (x ^ y ^ z)
128
129 P( A, B, C, D, 5, 4, 0xFFFA3942 );
130 P( D, A, B, C, 8, 11, 0x8771F681 );
131 P( C, D, A, B, 11, 16, 0x6D9D6122 );
132 P( B, C, D, A, 14, 23, 0xFDE5380C );
133 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
134 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
135 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
136 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
137 P( A, B, C, D, 13, 4, 0x289B7EC6 );
138 P( D, A, B, C, 0, 11, 0xEAA127FA );
139 P( C, D, A, B, 3, 16, 0xD4EF3085 );
140 P( B, C, D, A, 6, 23, 0x04881D05 );
141 P( A, B, C, D, 9, 4, 0xD9D4D039 );
142 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
143 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
144 P( B, C, D, A, 2, 23, 0xC4AC5665 );
145
146#undef F
147
148#define F(x,y,z) (y ^ (x | ~z))
149
150 P( A, B, C, D, 0, 6, 0xF4292244 );
151 P( D, A, B, C, 7, 10, 0x432AFF97 );
152 P( C, D, A, B, 14, 15, 0xAB9423A7 );
153 P( B, C, D, A, 5, 21, 0xFC93A039 );
154 P( A, B, C, D, 12, 6, 0x655B59C3 );
155 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
156 P( C, D, A, B, 10, 15, 0xFFEFF47D );
157 P( B, C, D, A, 1, 21, 0x85845DD1 );
158 P( A, B, C, D, 8, 6, 0x6FA87E4F );
159 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
160 P( C, D, A, B, 6, 15, 0xA3014314 );
161 P( B, C, D, A, 13, 21, 0x4E0811A1 );
162 P( A, B, C, D, 4, 6, 0xF7537E82 );
163 P( D, A, B, C, 11, 10, 0xBD3AF235 );
164 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
165 P( B, C, D, A, 9, 21, 0xEB86D391 );
166
167#undef F
168
169 ctx->state[0] += A;
170 ctx->state[1] += B;
171 ctx->state[2] += C;
172 ctx->state[3] += D;
173}
174
175void md5_update( md5_context *ctx, uint8 *input, uint32 length )
176{
177 uint32 left, fill;
178
179 if( ! length ) return;
180
181 left = ctx->total[0] & 0x3F;
182 fill = 64 - left;
183
184 ctx->total[0] += length;
185 ctx->total[0] &= 0xFFFFFFFF;
186
187 if( ctx->total[0] < length )
188 ctx->total[1]++;
189
190 if( left && length >= fill )
191 {
192 memcpy( (void *) (ctx->buffer + left),
193 (void *) input, fill );
194 md5_process( ctx, ctx->buffer );
195 length -= fill;
196 input += fill;
197 left = 0;
198 }
199
200 while( length >= 64 )
201 {
202 md5_process( ctx, input );
203 length -= 64;
204 input += 64;
205 }
206
207 if( length )
208 {
209 memcpy( (void *) (ctx->buffer + left),
210 (void *) input, length );
211 }
212}
213
214static uint8 md5_padding[64] =
215{
216 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
220};
221
222void md5_finish( md5_context *ctx, uint8 digest[16] )
223{
224 uint32 last, padn;
225 uint32 high, low;
226 uint8 msglen[8];
227
228 high = ( ctx->total[0] >> 29 )
229 | ( ctx->total[1] << 3 );
230 low = ( ctx->total[0] << 3 );
231
232 PUT_UINT32( low, msglen, 0 );
233 PUT_UINT32( high, msglen, 4 );
234
235 last = ctx->total[0] & 0x3F;
236 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
237
238 md5_update( ctx, md5_padding, padn );
239 md5_update( ctx, msglen, 8 );
240
241 PUT_UINT32( ctx->state[0], digest, 0 );
242 PUT_UINT32( ctx->state[1], digest, 4 );
243 PUT_UINT32( ctx->state[2], digest, 8 );
244 PUT_UINT32( ctx->state[3], digest, 12 );
245}
246
diff --git a/utils/mkimxboot/md5.h b/utils/mkimxboot/md5.h
new file mode 100644
index 0000000000..71fa395548
--- /dev/null
+++ b/utils/mkimxboot/md5.h
@@ -0,0 +1,25 @@
1#ifndef _MD5_H
2#define _MD5_H
3
4#ifndef uint8
5#define uint8 unsigned char
6#endif
7
8#ifndef uint32
9#define uint32 unsigned long int
10#endif
11
12typedef struct
13{
14 uint32 total[2];
15 uint32 state[4];
16 uint8 buffer[64];
17}
18md5_context;
19
20void md5_starts( md5_context *ctx );
21void md5_update( md5_context *ctx, uint8 *input, uint32 length );
22void md5_finish( md5_context *ctx, uint8 digest[16] );
23
24#endif /* md5.h */
25
diff --git a/utils/mkimxboot/mkimxboot.c b/utils/mkimxboot/mkimxboot.c
new file mode 100644
index 0000000000..0483b5aeee
--- /dev/null
+++ b/utils/mkimxboot/mkimxboot.c
@@ -0,0 +1,1123 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
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 <stdio.h>
22#include <stdlib.h>
23#include <stdarg.h>
24#include <string.h>
25#include <ctype.h>
26#include "mkimxboot.h"
27#include "sb.h"
28#include "dualboot.h"
29#include "md5.h"
30#include "elf.h"
31
32/* abstract structure to represent a Rockbox firmware. It can be a scrambled file
33 * or an ELF file or whatever. */
34struct rb_fw_t
35{
36 int nr_insts;
37 struct sb_inst_t *insts;
38 int entry_idx;
39};
40
41/* A firmware upgrade can contains several variants like recovery image, or
42 * images for different models */
43struct imx_fw_variant_desc_t
44{
45 /* Offset within file */
46 size_t offset;
47 /* Total size of the firmware */
48 size_t size;
49};
50
51/* Map a MD5 sum of the whole file to a model and describe the variants in it */
52struct imx_md5sum_t
53{
54 /* Device model */
55 enum imx_model_t model;
56 /* md5sum of the file */
57 char *md5sum;
58 /* Version string */
59 const char *version;
60 /* Variant descriptions */
61 struct imx_fw_variant_desc_t fw_variants[VARIANT_COUNT];
62};
63
64/* Describe how to produce a bootloader image for a specific model */
65struct imx_model_desc_t
66{
67 /* Descriptive name of this model */
68 const char *model_name;
69 /* Dualboot code for this model */
70 const unsigned char *dualboot;
71 /* Size of dualboot functions for this model */
72 int dualboot_size;
73 /* Model name used in the Rockbox header in ".sansa" files - these match the
74 -add parameter to the "scramble" tool */
75 const char *rb_model_name;
76 /* Model number used to initialise the checksum in the Rockbox header in
77 ".sansa" files - these are the same as MODEL_NUMBER in config-target.h */
78 const int rb_model_num;
79 /* Array of NULL-terminated keys */
80 struct crypto_key_t **keys;
81 /* Dualboot load address */
82 uint32_t dualboot_addr;
83 /* Bootloader load address */
84 uint32_t bootloader_addr;
85};
86
87/* Friendly names for variants */
88static const char *imx_fw_variant[] =
89{
90 [VARIANT_DEFAULT] = "default",
91 [VARIANT_ZENXFI2_RECOVERY] = "ZEN X-Fi2 Recovery",
92 [VARIANT_ZENXFI2_NAND] = "ZEN X-Fi2 NAND",
93 [VARIANT_ZENXFI2_SD] = "ZEN X-Fi2 eMMC/SD",
94 [VARIANT_ZENXFISTYLE_RECOVERY] = "ZEN X-Fi Style Recovery",
95 [VARIANT_ZENSTYLE_RECOVERY] = "ZEN Style 100/300 Recovery",
96};
97
98/* List of known MD5 sums for firmware upgrades */
99static const struct imx_md5sum_t imx_sums[] =
100{
101 /** Fuze+ */
102 {
103 /* Version 2.38.6 */
104 MODEL_FUZEPLUS, "c3e27620a877dc6b200b97dcb3e0ecc7", "2.38.6",
105 { [VARIANT_DEFAULT] = { 0, 34652624 } }
106 },
107 /** Zen X-Fi2 */
108 {
109 /* Version 1.23.01 */
110 MODEL_ZENXFI2, "e37e2c24abdff8e624d0a29f79157850", "1.23.01",
111 {
112 [VARIANT_ZENXFI2_RECOVERY] = { 602128, 684192},
113 [VARIANT_ZENXFI2_NAND] = { 1286320, 42406608 },
114 [VARIANT_ZENXFI2_SD] = { 43692928, 42304208 }
115 }
116 },
117 {
118 /* Version 1.23.01e */
119 MODEL_ZENXFI2, "2beff2168212d332f13cfc36ca46989d", "1.23.01e",
120 {
121 [VARIANT_ZENXFI2_RECOVERY] = { 0x93010, 684192},
122 [VARIANT_ZENXFI2_NAND] = { 0x13a0b0, 42410704 },
123 [VARIANT_ZENXFI2_SD] = { 0x29ac380, 42304208 }
124 }
125 },
126 /** Zen X-Fi3 */
127 {
128 /* Version 1.00.15e */
129 MODEL_ZENXFI3, "658a24eeef5f7186ca731085d8822a87", "1.00.15e",
130 { [VARIANT_DEFAULT] = {0, 18110576} }
131 },
132 {
133 /* Version 1.00.22e */
134 MODEL_ZENXFI3, "a5114cd45ea4554ec221f51a71083862", "1.00.22e",
135 { [VARIANT_DEFAULT] = {0, 18110576} }
136 },
137 {
138 /* Version 1.00.25 */
139 MODEL_ZENXFI3, "a41a3a78f86a4ac2879d194c6d528059", "1.00.25",
140 { [VARIANT_DEFAULT] = {0, 18110576 } }
141 },
142 {
143 /* Version 1.00.25e */
144 MODEL_ZENXFI3, "c180f57e2b2d62620f87a1d853f349ff", "1.00.25e",
145 { [VARIANT_DEFAULT] = {0, 18110576 } }
146 },
147 /** Zen X-Fi Style */
148 {
149 /* Version 1.03.04e */
150 MODEL_ZENXFISTYLE, "32a731b7f714e9f99a95991003759c98", "1.03.04",
151 {
152 [VARIANT_DEFAULT] = {842960, 29876944},
153 [VARIANT_ZENXFISTYLE_RECOVERY] = {610272, 232688},
154 }
155 },
156 {
157 /* Version 1.03.04e */
158 MODEL_ZENXFISTYLE, "2c7ee52d9984d85dd39aa49b3331e66c", "1.03.04e",
159 {
160 [VARIANT_DEFAULT] = {842960, 29876944},
161 [VARIANT_ZENXFISTYLE_RECOVERY] = {610272, 232688},
162 }
163 },
164 {
165 /* Version 1.03.04e */
166 MODEL_ZENSTYLE, "dbebec8fe666412061d9740ff68605dd", "1.03.04e",
167 {
168 [VARIANT_DEFAULT] = {758848, 6641344},
169 [VARIANT_ZENSTYLE_RECOVERY] = {610272, 148576},
170 }
171 },
172 /** Sony NWZ-E370 */
173 {
174 /* Version 1.00.00 */
175 MODEL_NWZE370, "a615fdb70b3e1bfb0355a5bc2bf237ab", "1.00.00",
176 { [VARIANT_DEFAULT] = {0, 16056320 } }
177 },
178 {
179 /* Version 1.00.01 */
180 MODEL_NWZE370, "ee83f3c6026cbcc07097867f06fd585f", "1.00.01",
181 { [VARIANT_DEFAULT] = {0, 16515072 } }
182 },
183 /** Sony NWZ-E360 */
184 {
185 /* Version 1.00.00 */
186 MODEL_NWZE360, "d0047f8a87d456a0032297b3c802a1ff", "1.00.00",
187 { [VARIANT_DEFAULT] = {0, 20652032 } }
188 },
189 /** Sony NWZ-E380 */
190 {
191 /* Version 1.00.00 */
192 MODEL_NWZE370, "412f8ccd453195c0bebcc1fd8376322f", "1.00.00",
193 { [VARIANT_DEFAULT] = {0, 16429056 } }
194 },
195 {
196 /* Version 1.00.200 */
197 MODEL_NWZE370, "75cfa51078261c547717e11a4676f1af", "1.00.200",
198 { [VARIANT_DEFAULT] = {0, 16429056 } }
199 }
200};
201
202static struct crypto_key_t zero_key =
203{
204 .method = CRYPTO_KEY,
205 .u.key = {0}
206};
207
208static struct crypto_key_t *list_zero_key[] = { &zero_key, NULL };
209static struct crypto_key_t *list_all_keys[] = { &zero_key, NULL };
210
211static const struct imx_model_desc_t imx_models[] =
212{
213 [MODEL_FUZEPLUS] = {"Fuze+", dualboot_fuzeplus, sizeof(dualboot_fuzeplus),
214 "fuz+", 72, list_zero_key, 0, 0x40000000 },
215 [MODEL_ZENXFI2] = {"Zen X-Fi2", dualboot_zenxfi2, sizeof(dualboot_zenxfi2),
216 "zxf2", 82, list_zero_key, 0, 0x40000000 },
217 [MODEL_ZENXFI3] = {"Zen X-Fi3", dualboot_zenxfi3, sizeof(dualboot_zenxfi3),
218 "zxf3", 83, list_zero_key, 0, 0x40000000 },
219 [MODEL_ZENXFISTYLE] = {"Zen X-Fi Style", dualboot_zenxfistyle, sizeof(dualboot_zenxfistyle),
220 "zxfs", 94, list_zero_key, 0, 0x40000000 },
221 [MODEL_ZENSTYLE] = {"Zen Style 100/300", NULL, 0, "", -1, list_zero_key, 0, 0x40000000 },
222 [MODEL_NWZE370] = {"NWZ-E370", dualboot_nwze370, sizeof(dualboot_nwze370),
223 "e370", 88, list_zero_key, 0, 0x40000000 },
224 [MODEL_NWZE360] = {"NWZ-E360", dualboot_nwze360, sizeof(dualboot_nwze360),
225 "e360", 89, list_zero_key, 0, 0x40000000 },
226};
227
228#define NR_IMX_SUMS (sizeof(imx_sums) / sizeof(imx_sums[0]))
229#define NR_IMX_MODELS (sizeof(imx_models) / sizeof(imx_models[0]))
230
231#define MAGIC_ROCK 0x726f636b /* 'rock' */
232#define MAGIC_RECOVERY 0xfee1dead
233#define MAGIC_NORMAL 0xcafebabe
234#define MAGIC_CHARGE 0x67726863 /* 'chrg' */
235
236const char *imx_error_to_string(enum imx_error_t err)
237{
238 switch(err)
239 {
240 case IMX_SUCCESS: return "success";
241 case IMX_ERROR: return "error";
242 case IMX_OPEN_ERROR: return "open error";
243 case IMX_READ_ERROR: return "read error";
244 case IMX_NO_MATCH: return "no match";
245 case IMX_BOOT_INVALID: return "invalid";
246 case IMX_BOOT_MISMATCH: return "mismatch";
247 case IMX_BOOT_CHECKSUM_ERROR: return "checksum error";
248 case IMX_DONT_KNOW_HOW_TO_PATCH: return "don't know how to patch";
249 case IMX_VARIANT_MISMATCH: return "variant mismatch";
250 case IMX_WRITE_ERROR: return "write error";
251 case IMX_FIRST_SB_ERROR: return "sb error";
252 case IMX_MODEL_MISMATCH: return "model mismatch";
253 default: return "unknown error";
254 }
255}
256
257static void add_key_list(struct crypto_key_t **list)
258{
259 while(*list != NULL)
260 add_keys(*list++, 1);
261}
262
263static int rb_fw_get_sb_inst_count(struct rb_fw_t *fw)
264{
265 return fw->nr_insts;
266}
267
268/* fill sb instruction for the firmware, fill fill rb_fw_get_sb_inst_count() instructions */
269static void rb_fw_fill_sb(struct rb_fw_t *fw, struct sb_inst_t *inst,
270 uint32_t entry_arg)
271{
272 memcpy(inst, fw->insts, fw->nr_insts * sizeof(struct sb_inst_t));
273 /* copy data if needed */
274 for(int i = 0; i < fw->nr_insts; i++)
275 if(fw->insts[i].inst == SB_INST_LOAD)
276 fw->insts[i].data = memdup(fw->insts[i].data, fw->insts[i].size);
277 /* replace call argument of the entry point */
278 inst[fw->entry_idx].argument = entry_arg;
279}
280
281static enum imx_error_t patch_std_zero_host_play(int jump_before,
282 struct imx_option_t opt, struct sb_file_t *sb_file, struct rb_fw_t boot_fw)
283{
284 /* We assume the file has three boot sections: ____, host, play and one
285 * resource section rsrc.
286 *
287 * Dual Boot:
288 * ----------
289 * We patch the file by inserting the dualboot code before the <jump_before>th
290 * call in the ____ section. We give it as argument the section name 'rock'
291 * and add a section called 'rock' after rsrc which contains the bootloader.
292 *
293 * Single Boot & Recovery:
294 * -----------------------
295 * We patch the file by inserting the bootloader code after the <jump_before>th
296 * call in the ____ section and get rid of everything else. In recovery mode,
297 * we give 0xfee1dead as argument */
298
299 /* used to manipulate entries */
300 int nr_boot_inst = rb_fw_get_sb_inst_count(&boot_fw);
301
302 /* first locate the good instruction */
303 struct sb_section_t *sec = &sb_file->sections[0];
304 int jump_idx = 0;
305 while(jump_idx < sec->nr_insts && jump_before > 0)
306 if(sec->insts[jump_idx++].inst == SB_INST_CALL)
307 jump_before--;
308 if(jump_idx == sec->nr_insts)
309 {
310 printf("[ERR] Cannot locate call in section ____\n");
311 return IMX_DONT_KNOW_HOW_TO_PATCH;
312 }
313
314 if(opt.output == IMX_DUALBOOT)
315 {
316 /* create a new instruction array with a hole for two instructions */
317 struct sb_inst_t *new_insts = xmalloc(sizeof(struct sb_inst_t) * (sec->nr_insts + 2));
318 memcpy(new_insts, sec->insts, sizeof(struct sb_inst_t) * jump_idx);
319 memcpy(new_insts + jump_idx + 2, sec->insts + jump_idx,
320 sizeof(struct sb_inst_t) * (sec->nr_insts - jump_idx));
321 /* first instruction is be a load */
322 struct sb_inst_t *load = &new_insts[jump_idx];
323 memset(load, 0, sizeof(struct sb_inst_t));
324 load->inst = SB_INST_LOAD;
325 load->size = imx_models[opt.model].dualboot_size;
326 load->addr = imx_models[opt.model].dualboot_addr;
327 /* duplicate memory because it will be free'd */
328 load->data = memdup(imx_models[opt.model].dualboot,
329 imx_models[opt.model].dualboot_size);
330 /* second instruction is a call */
331 struct sb_inst_t *call = &new_insts[jump_idx + 1];
332 memset(call, 0, sizeof(struct sb_inst_t));
333 call->inst = SB_INST_CALL;
334 call->addr = imx_models[opt.model].dualboot_addr;
335 call->argument = MAGIC_ROCK;
336 /* free old instruction array */
337 free(sec->insts);
338 sec->insts = new_insts;
339 sec->nr_insts += 2;
340
341 /* create a new section */
342 struct sb_section_t rock_sec;
343 memset(&rock_sec, 0, sizeof(rock_sec));
344 /* section can have any number of instructions */
345 rock_sec.identifier = MAGIC_ROCK;
346 rock_sec.alignment = BLOCK_SIZE;
347 rock_sec.nr_insts = nr_boot_inst;
348 rock_sec.insts = xmalloc(nr_boot_inst * sizeof(struct sb_inst_t));
349 rb_fw_fill_sb(&boot_fw, rock_sec.insts, MAGIC_NORMAL);
350
351 sb_file->sections = augment_array(sb_file->sections,
352 sizeof(struct sb_section_t), sb_file->nr_sections,
353 &rock_sec, 1);
354 sb_file->nr_sections++;
355
356 return IMX_SUCCESS;
357 }
358 else if(opt.output == IMX_SINGLEBOOT || opt.output == IMX_RECOVERY)
359 {
360 bool recovery = (opt.output == IMX_RECOVERY);
361 /* remove everything after the call and add instructions for firmware */
362 struct sb_inst_t *new_insts = xmalloc(sizeof(struct sb_inst_t) * (jump_idx + nr_boot_inst));
363 memcpy(new_insts, sec->insts, sizeof(struct sb_inst_t) * jump_idx);
364 for(int i = jump_idx; i < sec->nr_insts; i++)
365 sb_free_instruction(sec->insts[i]);
366 rb_fw_fill_sb(&boot_fw, &new_insts[jump_idx], recovery ? MAGIC_RECOVERY : MAGIC_NORMAL);
367
368 free(sec->insts);
369 sec->insts = new_insts;
370 sec->nr_insts = jump_idx + nr_boot_inst;
371 /* remove all other sections */
372 for(int i = 1; i < sb_file->nr_sections; i++)
373 sb_free_section(sb_file->sections[i]);
374 struct sb_section_t *new_sec = xmalloc(sizeof(struct sb_section_t));
375 memcpy(new_sec, &sb_file->sections[0], sizeof(struct sb_section_t));
376 free(sb_file->sections);
377 sb_file->sections = new_sec;
378 sb_file->nr_sections = 1;
379
380 return IMX_SUCCESS;
381 }
382 else if(opt.output == IMX_CHARGE)
383 {
384 /* throw away everything except the dualboot stub with a special argument */
385 struct sb_inst_t *new_insts = xmalloc(sizeof(struct sb_inst_t) * 2);
386 /* first instruction is be a load */
387 struct sb_inst_t *load = &new_insts[0];
388 memset(load, 0, sizeof(struct sb_inst_t));
389 load->inst = SB_INST_LOAD;
390 load->size = imx_models[opt.model].dualboot_size;
391 load->addr = imx_models[opt.model].dualboot_addr;
392 /* duplicate memory because it will be free'd */
393 load->data = memdup(imx_models[opt.model].dualboot,
394 imx_models[opt.model].dualboot_size);
395 /* second instruction is a call */
396 struct sb_inst_t *call = &new_insts[1];
397 memset(call, 0, sizeof(struct sb_inst_t));
398 call->inst = SB_INST_CALL;
399 call->addr = imx_models[opt.model].dualboot_addr;
400 call->argument = MAGIC_CHARGE;
401 /* free old instruction array */
402 free(sec->insts);
403 sec->insts = new_insts;
404 sec->nr_insts = 2;
405 /* remove all other sections */
406 for(int i = 1; i < sb_file->nr_sections; i++)
407 sb_free_section(sb_file->sections[i]);
408 struct sb_section_t *new_sec = xmalloc(sizeof(struct sb_section_t));
409 memcpy(new_sec, &sb_file->sections[0], sizeof(struct sb_section_t));
410 free(sb_file->sections);
411 sb_file->sections = new_sec;
412 sb_file->nr_sections = 1;
413
414 return IMX_SUCCESS;
415 }
416 else
417 {
418 printf("[ERR] Bad output type !\n");
419 return IMX_DONT_KNOW_HOW_TO_PATCH;
420 }
421}
422
423static enum imx_error_t parse_subversion(const char *s, const char *end, uint16_t *ver)
424{
425 int len = (end == NULL) ? strlen(s) : end - s;
426 if(len > 4)
427 {
428 printf("[ERR] Bad subversion override '%s' (too long)\n", s);
429 return IMX_ERROR;
430 }
431 *ver = 0;
432 for(int i = 0; i < len; i++)
433 {
434 if(!isdigit(s[i]))
435 {
436 printf("[ERR] Bad subversion override '%s' (not a digit)\n", s);
437 return IMX_ERROR;
438 }
439 *ver = *ver << 4 | (s[i] - '0');
440 }
441 return IMX_SUCCESS;
442}
443
444static enum imx_error_t parse_version(const char *s, struct sb_version_t *ver)
445{
446 const char *dot1 = strchr(s, '.');
447 if(dot1 == NULL)
448 {
449 printf("[ERR] Bad version override '%s' (missing dot)\n", s);
450 return IMX_ERROR;
451 }
452 const char *dot2 = strchr(dot1 + 1, '.');
453 if(dot2 == NULL)
454 {
455 printf("[ERR] Bad version override '%s' (missing second dot)\n", s);
456 return IMX_ERROR;
457 }
458 enum imx_error_t ret = parse_subversion(s, dot1, &ver->major);
459 if(ret != IMX_SUCCESS) return ret;
460 ret = parse_subversion(dot1 + 1, dot2, &ver->minor);
461 if(ret != IMX_SUCCESS) return ret;
462 ret = parse_subversion(dot2 + 1, NULL, &ver->revision);
463 if(ret != IMX_SUCCESS) return ret;
464 return IMX_SUCCESS;
465}
466
467static enum imx_error_t patch_firmware(struct imx_option_t opt,
468 struct sb_file_t *sb_file, struct rb_fw_t boot_fw)
469{
470 if(opt.force_version)
471 {
472 enum imx_error_t err = parse_version(opt.force_version, &sb_file->product_ver);
473 if(err != IMX_SUCCESS)
474 return err;
475 err = parse_version(opt.force_version, &sb_file->component_ver);
476 if(err != IMX_SUCCESS)
477 return err;
478 }
479 switch(opt.model)
480 {
481 case MODEL_FUZEPLUS:
482 /* The Fuze+ uses the standard ____, host, play sections, patch after third
483 * call in ____ section */
484 return patch_std_zero_host_play(3, opt, sb_file, boot_fw);
485 case MODEL_ZENXFI3:
486 /* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third
487 * call in ____ section. Although sections names use the S variant, they are standard. */
488 return patch_std_zero_host_play(3, opt, sb_file, boot_fw);
489 case MODEL_NWZE360:
490 case MODEL_NWZE370:
491 /* The NWZ-E360/E370 uses the standard ____, host, play sections, patch after first
492 * call in ____ section. */
493 return patch_std_zero_host_play(1, opt, sb_file, boot_fw);
494 case MODEL_ZENXFI2:
495 /* The ZEN X-Fi2 has two types of firmware: recovery and normal.
496 * Normal uses the standard ___, host, play sections and recovery only ____ */
497 switch(opt.fw_variant)
498 {
499 case VARIANT_ZENXFI2_RECOVERY:
500 case VARIANT_ZENXFI2_NAND:
501 case VARIANT_ZENXFI2_SD:
502 return patch_std_zero_host_play(1, opt, sb_file, boot_fw);
503 default:
504 return IMX_DONT_KNOW_HOW_TO_PATCH;
505 }
506 break;
507 case MODEL_ZENXFISTYLE:
508 /* The ZEN X-Fi Style uses the standard ____, host, play sections, patch after first
509 * call in ____ section. */
510 return patch_std_zero_host_play(1, opt, sb_file, boot_fw);
511 default:
512 return IMX_DONT_KNOW_HOW_TO_PATCH;
513 }
514}
515
516static enum imx_error_t unpatch_std_zero_host_play(int jump_before,
517 struct imx_option_t opt, struct sb_file_t *sb_file)
518{
519 /* find rockbox section */
520 int rb_sec = -1;
521 for(int i = 0; i < sb_file->nr_sections; i++)
522 if(sb_file->sections[i].identifier == MAGIC_ROCK)
523 rb_sec = i;
524 if(rb_sec == -1)
525 {
526 printf("[ERR][INTERNAL] Cannot find rockbox section\n");
527 return IMX_ERROR;
528 }
529 /** 1) remove rockbox section */
530 /* free rockbox section */
531 sb_free_section(sb_file->sections[rb_sec]);
532 /* create a new array of sections */
533 sb_file->nr_sections--;
534 struct sb_section_t *new_sec = xmalloc(sb_file->nr_sections * sizeof(struct sb_section_t));
535 /* copy all sections exception rockbox */
536 memcpy(new_sec, sb_file->sections, rb_sec * sizeof(struct sb_section_t));
537 memcpy(new_sec + rb_sec, sb_file->sections + rb_sec + 1,
538 (sb_file->nr_sections - rb_sec) * sizeof(struct sb_section_t));
539 /* free old array and replace it */
540 free(sb_file->sections);
541 sb_file->sections = new_sec;
542
543 /** 2) remove patch instructions in boot section */
544 struct sb_section_t *sec = &sb_file->sections[0];
545 int jump_idx = 0;
546 while(jump_idx < sec->nr_insts && jump_before > 0)
547 if(sec->insts[jump_idx++].inst == SB_INST_CALL)
548 jump_before--;
549 if(jump_idx == sec->nr_insts)
550 {
551 printf("[ERR] Cannot locate call in section ____\n");
552 return IMX_DONT_KNOW_HOW_TO_PATCH;
553 }
554 /* free two instructions */
555 sb_free_instruction(sec->insts[jump_idx]);
556 sb_free_instruction(sec->insts[jump_idx + 1]);
557 /* create a new array of instructions */
558 sec->nr_insts -= 2;
559 struct sb_inst_t *new_inst = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t));
560 /* copy all instructions except the two patch to remove */
561 memcpy(new_inst, sec->insts, jump_idx * sizeof(struct sb_inst_t));
562 memcpy(new_inst + jump_idx, sec->insts + jump_idx + 2,
563 (sec->nr_insts - jump_idx) * sizeof(struct sb_inst_t));
564 /* free old array and replace it */
565 free(sec->insts);
566 sec->insts = new_inst;
567
568 return IMX_SUCCESS;
569}
570
571static enum imx_error_t unpatch_firmware(struct imx_option_t opt,
572 struct sb_file_t *sb_file)
573{
574 /* keep consistent with patch_firmware */
575 switch(opt.model)
576 {
577 case MODEL_FUZEPLUS:
578 /* The Fuze+ uses the standard ____, host, play sections, patch after third
579 * call in ____ section */
580 return unpatch_std_zero_host_play(3, opt, sb_file);
581 case MODEL_ZENXFI3:
582 /* The ZEN X-Fi3 uses the standard ____, hSst, pSay sections, patch after third
583 * call in ____ section. Although sections names use the S variant, they are standard. */
584 return unpatch_std_zero_host_play(3, opt, sb_file);
585 case MODEL_NWZE360:
586 case MODEL_NWZE370:
587 /* The NWZ-E360/E370 uses the standard ____, host, play sections, patch after first
588 * call in ____ section. */
589 return unpatch_std_zero_host_play(1, opt, sb_file);
590 case MODEL_ZENXFI2:
591 /* The ZEN X-Fi2 has two types of firmware: recovery and normal.
592 * Normal uses the standard ___, host, play sections and recovery only ____ */
593 switch(opt.fw_variant)
594 {
595 case VARIANT_ZENXFI2_RECOVERY:
596 case VARIANT_ZENXFI2_NAND:
597 case VARIANT_ZENXFI2_SD:
598 return unpatch_std_zero_host_play(1, opt, sb_file);
599 default:
600 return IMX_DONT_KNOW_HOW_TO_PATCH;
601 }
602 break;
603 case MODEL_ZENXFISTYLE:
604 /* The ZEN X-Fi Style uses the standard ____, host, play sections, patch after first
605 * call in ____ section. */
606 return unpatch_std_zero_host_play(1, opt, sb_file);
607 default:
608 return IMX_DONT_KNOW_HOW_TO_PATCH;
609 }
610}
611
612static uint32_t get_uint32be(unsigned char *p)
613{
614 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
615}
616
617void dump_imx_dev_info(const char *prefix)
618{
619 printf("%smkimxboot models:\n", prefix);
620 for(int i = 0; i < NR_IMX_MODELS; i++)
621 {
622 printf("%s %s: idx=%d rb_model=%s rb_num=%d\n", prefix,
623 imx_models[i].model_name, i, imx_models[i].rb_model_name,
624 imx_models[i].rb_model_num);
625 }
626 printf("%smkimxboot variants:\n", prefix);
627 for(int i = 0; i < VARIANT_COUNT; i++)
628 {
629 printf("%s %d: %s\n", prefix, i, imx_fw_variant[i]);
630 }
631 printf("%smkimxboot mapping:\n", prefix);
632 for(int i = 0; i < NR_IMX_SUMS; i++)
633 {
634 printf("%s md5sum=%s -> idx=%d, ver=%s\n", prefix, imx_sums[i].md5sum,
635 imx_sums[i].model, imx_sums[i].version);
636 for(int j = 0; j < VARIANT_COUNT; j++)
637 if(imx_sums[i].fw_variants[j].size)
638 printf("%s variant=%d -> offset=%#x size=%#x\n", prefix,
639 j, (unsigned)imx_sums[i].fw_variants[j].offset,
640 (unsigned)imx_sums[i].fw_variants[j].size);
641 }
642}
643
644/* find an entry into imx_sums which matches the MD5 sum of a file */
645static enum imx_error_t find_model_by_md5sum(uint8_t file_md5sum[16], int *md5_idx)
646{
647 int i = 0;
648 while(i < NR_IMX_SUMS)
649 {
650 uint8_t md5[20];
651 if(strlen(imx_sums[i].md5sum) != 32)
652 {
653 printf("[INFO] Invalid MD5 sum in imx_sums\n");
654 return IMX_ERROR;
655 }
656 for(int j = 0; j < 16; j++)
657 {
658 uint8_t a, b;
659 if(convxdigit(imx_sums[i].md5sum[2 * j], &a) || convxdigit(imx_sums[i].md5sum[2 * j + 1], &b))
660 {
661 printf("[ERR][INTERNAL] Bad checksum format: %s\n", imx_sums[i].md5sum);
662 return IMX_ERROR;
663 }
664 md5[j] = (a << 4) | b;
665 }
666 if(memcmp(file_md5sum, md5, 16) == 0)
667 break;
668 i++;
669 }
670 if(i == NR_IMX_SUMS)
671 {
672 printf("[WARN] MD5 sum doesn't match any known file\n");
673 return IMX_NO_MATCH;
674 }
675 *md5_idx = i;
676 return IMX_SUCCESS;
677}
678
679/* read a file to a buffer */
680static enum imx_error_t read_file(const char *file, void **buffer, size_t *size)
681{
682 FILE *f = fopen(file, "rb");
683 if(f == NULL)
684 {
685 printf("[ERR] Cannot open file '%s' for reading: %m\n", file);
686 return IMX_OPEN_ERROR;
687 }
688 fseek(f, 0, SEEK_END);
689 *size = ftell(f);
690 fseek(f, 0, SEEK_SET);
691 *buffer = xmalloc(*size);
692 if(fread(*buffer, *size, 1, f) != 1)
693 {
694 free(*buffer);
695 fclose(f);
696 printf("[ERR] Cannot read file '%s': %m\n", file);
697 return IMX_READ_ERROR;
698 }
699 fclose(f);
700 return IMX_SUCCESS;
701}
702
703/* write a file from a buffer */
704static enum imx_error_t write_file(const char *file, void *buffer, size_t size)
705{
706 FILE *f = fopen(file, "wb");
707 if(f == NULL)
708 {
709 printf("[ERR] Cannot open file '%s' for writing: %m\n", file);
710 return IMX_OPEN_ERROR;
711 }
712 if(fwrite(buffer, size, 1, f) != 1)
713 {
714 fclose(f);
715 printf("[ERR] Cannot write file '%s': %m\n", file);
716 return IMX_WRITE_ERROR;
717 }
718 fclose(f);
719 return IMX_SUCCESS;
720}
721
722/* compute MD5 sum of a buffer */
723static enum imx_error_t compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md5sum[16])
724{
725 md5_context ctx;
726 md5_starts(&ctx);
727 md5_update(&ctx, buf, sz);
728 md5_finish(&ctx, file_md5sum);
729 return IMX_SUCCESS;
730}
731
732/* compute MD5 sum of a buffer */
733static enum imx_error_t compute_soft_md5sum_buf(struct sb_file_t *sb, uint8_t file_md5sum[16])
734{
735 md5_context ctx;
736 md5_starts(&ctx);
737#define hash(obj) \
738 md5_update(&ctx, (void *)&obj, sizeof(obj))
739 /* various header fiels */
740 hash(sb->timestamp);
741 hash(sb->drive_tag);
742 hash(sb->drive_tag);
743 hash(sb->first_boot_sec_id);
744 hash(sb->flags);
745 hash(sb->product_ver);
746 hash(sb->component_ver);
747
748 for(int i = 0; i < sb->nr_sections; i++)
749 {
750 struct sb_section_t *sec = &sb->sections[i];
751 hash(sec->identifier);
752 uint32_t flags = sec->other_flags;
753 if(!sec->is_data)
754 flags |= SECTION_BOOTABLE;
755 if(sec->is_cleartext)
756 flags |= SECTION_CLEARTEXT;
757 hash(flags);
758
759 for(int j = 0; j < sec->nr_insts; j++)
760 {
761 struct sb_inst_t *inst = &sec->insts[j];
762 switch(inst->inst)
763 {
764 case SB_INST_NOP:
765 /* ignore them totally because they are used for padding */
766 break;
767 case SB_INST_LOAD:
768 hash(inst->inst);
769 hash(inst->addr);
770 md5_update(&ctx, inst->data, inst->size);
771 break;
772 case SB_INST_FILL:
773 hash(inst->inst);
774 hash(inst->addr);
775 hash(inst->pattern);
776 break;
777 case SB_INST_JUMP:
778 case SB_INST_CALL:
779 hash(inst->inst);
780 hash(inst->addr);
781 hash(inst->argument);
782 break;
783 case SB_INST_MODE:
784 hash(inst->inst);
785 hash(inst->argument);
786 break;
787 case SB_INST_DATA:
788 md5_update(&ctx, inst->data, inst->size);
789 break;
790 default:
791 printf("[ERR][INTERNAL] Unexpected instruction %d\n", inst->inst);
792 return IMX_ERROR;
793 }
794 }
795 }
796#undef hash
797 md5_finish(&ctx, file_md5sum);
798 return IMX_SUCCESS;
799}
800
801/* compute MD5 of a file */
802enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16])
803{
804 void *buf;
805 size_t sz;
806 enum imx_error_t err = read_file(file, &buf, &sz);
807 if(err != IMX_SUCCESS)
808 return err;
809 compute_md5sum_buf(buf, sz, file_md5sum);
810 free(buf);
811 return IMX_SUCCESS;
812}
813
814/* compute soft MD5 of a file */
815enum imx_error_t compute_soft_md5sum(const char *file, uint8_t soft_md5sum[16])
816{
817 clear_keys();
818 add_key_list(list_all_keys);
819 /* read file */
820 enum sb_error_t err;
821 struct sb_file_t *sb = sb_read_file(file, false, NULL, generic_std_printf, &err);
822 if(sb == NULL)
823 {
824 printf("[ERR] Cannot load SB file: %d\n", err);
825 return err;
826 }
827 /* compute sum */
828 err = compute_soft_md5sum_buf(sb, soft_md5sum);
829 /* release file */
830 sb_free(sb);
831 return err;
832}
833
834/* Load a rockbox firwmare from a buffer. Data is copied. Assume firmware is
835 * using our scramble format. */
836static enum imx_error_t rb_fw_load_buf_scramble(struct rb_fw_t *fw, uint8_t *buf,
837 size_t sz, enum imx_model_t model)
838{
839 if(sz < 8)
840 {
841 printf("[ERR] Bootloader file is too small to be valid\n");
842 return IMX_BOOT_INVALID;
843 }
844 /* check model name */
845 uint8_t *name = buf + 4;
846 if(memcmp(name, imx_models[model].rb_model_name, 4) != 0)
847 {
848 printf("[ERR] Bootloader model doesn't match found model for input file\n");
849 return IMX_BOOT_MISMATCH;
850 }
851 /* check checksum */
852 uint32_t sum = imx_models[model].rb_model_num;
853 for(int i = 8; i < sz; i++)
854 sum += buf[i];
855 if(sum != get_uint32be(buf))
856 {
857 printf("[ERR] Bootloader checksum mismatch\n");
858 return IMX_BOOT_CHECKSUM_ERROR;
859 }
860 /* two instructions: load and jump */
861 fw->nr_insts = 2;
862 fw->entry_idx = 1;
863 fw->insts = xmalloc(fw->nr_insts * sizeof(struct sb_inst_t));
864 memset(fw->insts, 0, fw->nr_insts * sizeof(struct sb_inst_t));
865 fw->insts[0].inst = SB_INST_LOAD;
866 fw->insts[0].addr = imx_models[model].bootloader_addr;
867 fw->insts[0].size = sz - 8;
868 fw->insts[0].data = memdup(buf + 8, sz - 8);
869 fw->insts[1].inst = SB_INST_JUMP;
870 fw->insts[1].addr = imx_models[model].bootloader_addr;
871 return IMX_SUCCESS;
872}
873
874struct elf_user_t
875{
876 void *buf;
877 size_t sz;
878};
879
880static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
881{
882 struct elf_user_t *u = user;
883 if(addr + count <= u->sz)
884 {
885 memcpy(buf, u->buf + addr, count);
886 return true;
887 }
888 else
889 return false;
890}
891
892/* Load a rockbox firwmare from a buffer. Data is copied. Assume firmware is
893 * using ELF format. */
894static enum imx_error_t rb_fw_load_buf_elf(struct rb_fw_t *fw, uint8_t *buf,
895 size_t sz, enum imx_model_t model)
896{
897 struct elf_params_t elf;
898 struct elf_user_t user;
899 user.buf = buf;
900 user.sz = sz;
901 elf_init(&elf);
902 if(!elf_read_file(&elf, elf_read, generic_std_printf, &user))
903 {
904 elf_release(&elf);
905 printf("[ERR] Error parsing ELF file\n");
906 return IMX_BOOT_INVALID;
907 }
908 fw->nr_insts = elf_get_nr_sections(&elf) + 1;
909 fw->insts = xmalloc(fw->nr_insts * sizeof(struct sb_inst_t));
910 fw->entry_idx = fw->nr_insts - 1;
911 memset(fw->insts, 0, fw->nr_insts * sizeof(struct sb_inst_t));
912 struct elf_section_t *sec = elf.first_section;
913 for(int i = 0; sec; i++, sec = sec->next)
914 {
915 fw->insts[i].addr = elf_translate_virtual_address(&elf, sec->addr);
916 fw->insts[i].size = sec->size;
917 if(sec->type == EST_LOAD)
918 {
919 fw->insts[i].inst = SB_INST_LOAD;
920 fw->insts[i].data = memdup(sec->section, sec->size);
921 }
922 else if(sec->type == EST_FILL)
923 {
924 fw->insts[i].inst = SB_INST_FILL;
925 fw->insts[i].pattern = sec->pattern;
926 }
927 else
928 {
929 printf("[WARN] Warning parsing ELF file: unsupported section type mapped to NOP!\n");
930 fw->insts[i].inst = SB_INST_NOP;
931 }
932 }
933 fw->insts[fw->nr_insts - 1].inst = SB_INST_JUMP;
934 if(!elf_get_start_addr(&elf, &fw->insts[fw->nr_insts - 1].addr))
935 {
936 elf_release(&elf);
937 printf("[ERROR] Error parsing ELF file: it has no entry point!\n");
938 return IMX_BOOT_INVALID;
939 }
940 elf_release(&elf);
941 return IMX_SUCCESS;
942}
943
944/* Load a rockbox firwmare from a buffer. Data is copied. */
945static enum imx_error_t rb_fw_load_buf(struct rb_fw_t *fw, uint8_t *buf,
946 size_t sz, enum imx_model_t model)
947{
948 /* detect file format */
949 if(sz >= 4 && buf[0] == 0x7f && memcmp(buf + 1, "ELF", 3) == 0)
950 return rb_fw_load_buf_elf(fw, buf, sz, model);
951 else
952 return rb_fw_load_buf_scramble(fw, buf, sz, model);
953}
954
955/* load a rockbox firmware from a file. */
956static enum imx_error_t rb_fw_load(struct rb_fw_t *fw, const char *file,
957 enum imx_model_t model)
958{
959 void *buf;
960 size_t sz;
961 int ret = read_file(file, &buf, &sz);
962 if(ret == IMX_SUCCESS)
963 {
964 ret = rb_fw_load_buf(fw, buf, sz, model);
965 free(buf);
966 }
967 return ret;
968}
969
970/* free rockbox firmware */
971static void rb_fw_free(struct rb_fw_t *fw)
972{
973 for(int i = 0; i < fw->nr_insts; i++)
974 sb_free_instruction(fw->insts[i]);
975 free(fw->insts);
976 memset(fw, 0, sizeof(struct rb_fw_t));
977}
978
979static bool contains_rockbox_bootloader(struct sb_file_t *sb_file)
980{
981 for(int i = 0; i < sb_file->nr_sections; i++)
982 if(sb_file->sections[i].identifier == MAGIC_ROCK)
983 return true;
984 return false;
985}
986
987/* modify sb_file to produce requested boot image */
988static enum imx_error_t make_boot(struct sb_file_t *sb_file, const char *bootfile,
989 struct imx_option_t opt)
990{
991 /* things went smoothly, we have a SB image but it may not be suitable as an
992 * input image: if it contains a rockbox bootloader, we need to remove it */
993 if(contains_rockbox_bootloader(sb_file))
994 {
995 printf("[INFO] SB file contains a Rockbox bootloader, trying to remove it...\n");
996 enum imx_error_t ret = unpatch_firmware(opt, sb_file);
997 if(ret != IMX_SUCCESS)
998 return ret;
999 }
1000 /* if asked to produce OF, don't do anything more */
1001 if(opt.output == IMX_ORIG_FW)
1002 return IMX_SUCCESS;
1003 /* load rockbox file */
1004 struct rb_fw_t boot_fw;
1005 enum imx_error_t ret = rb_fw_load(&boot_fw, bootfile, opt.model);
1006 if(ret != IMX_SUCCESS)
1007 return ret;
1008 /* produce file */
1009 ret = patch_firmware(opt, sb_file, boot_fw);
1010 rb_fw_free(&boot_fw);
1011 return ret;
1012}
1013
1014enum imx_error_t mkimxboot(const char *infile, const char *bootfile,
1015 const char *outfile, struct imx_option_t opt)
1016{
1017 /* sanity check */
1018 if(opt.fw_variant >= VARIANT_COUNT || opt.model >= MODEL_COUNT)
1019 return IMX_ERROR;
1020 /* dump tables */
1021 dump_imx_dev_info("[INFO] ");
1022 /* load file */
1023 void *buf;
1024 size_t offset = 0, size = 0;
1025 enum imx_error_t ret = read_file(infile, &buf, &size);
1026 if(ret != IMX_SUCCESS)
1027 return ret;
1028 /* compute MD5 sum of the file */
1029 uint8_t file_md5sum[16];
1030 compute_md5sum_buf(buf, size, file_md5sum);
1031 printf("[INFO] MD5 sum of the file: ");
1032 for(int i = 0; i < 16; i++)
1033 printf("%02x", file_md5sum[i]);
1034 printf("\n");
1035 /* find model */
1036 int md5_idx;
1037 ret = find_model_by_md5sum(file_md5sum, &md5_idx);
1038 /* is this a known firmware upgrade ? */
1039 if(ret == IMX_SUCCESS)
1040 {
1041 enum imx_model_t model = imx_sums[md5_idx].model;
1042 printf("[INFO] File is for model %d (%s, version %s)\n", model,
1043 imx_models[model].model_name, imx_sums[md5_idx].version);
1044 /* check the model is the expected one */
1045 if(opt.model == MODEL_UNKNOWN)
1046 opt.model = model;
1047 else if(opt.model != model)
1048 {
1049 printf("[ERR] Model mismatch, was expecting model %d (%s)\n",
1050 opt.model, imx_models[opt.model].model_name);
1051 free(buf);
1052 return IMX_MODEL_MISMATCH;
1053 }
1054 /* use database values */
1055 offset = imx_sums[md5_idx].fw_variants[opt.fw_variant].offset;
1056 size = imx_sums[md5_idx].fw_variants[opt.fw_variant].size;
1057 if(size == 0)
1058 {
1059 printf("[ERR] Input file does not contain variant '%s'\n", imx_fw_variant[opt.fw_variant]);
1060 free(buf);
1061 return IMX_VARIANT_MISMATCH;
1062 }
1063 /* special case: if we need to produce the OF, just bypass read/write of
1064 * the SB file and output this chunk of the file. This is faster and it
1065 * also avoids modifying the OF by reconstructing it */
1066 if(opt.output == IMX_ORIG_FW)
1067 {
1068 printf("[INFO] Extracting original firmware...\n");
1069 ret = write_file(outfile, buf + offset, size);
1070 free(buf);
1071 return ret;
1072 }
1073 }
1074 else
1075 {
1076 printf("[INFO] File doesn't have a known MD5 sum, assuming it's a SB image...\n");
1077 /* image didn't match, so we expect the file to be a raw SB image, either
1078 * produced by mkimxboot when uninstalling bootloader or after installing RB,
1079 * so load all known keys and go on */
1080
1081 /* To be more user friendly, give a nice error message if we detect
1082 * the file is not a SB file */
1083 if(guess_sb_version(infile) == SB_VERSION_UNK)
1084 {
1085 printf("[ERR] Your firmware doesn't look like a SB file\n");
1086 printf("[ERR] This is probably a firmware upgrade\n");
1087 printf("[ERR] Unfortunately, this tool doesn't know about it yet\n");
1088 printf("[ERR] Please report to the developers to add it\n");
1089 free(buf);
1090 return IMX_ERROR;
1091 }
1092 }
1093 /* to proceed further, we need to know the model */
1094 if(opt.model == MODEL_UNKNOWN)
1095 {
1096 printf("[ERR] Cannot do processing of soft image without knowing the model\n");
1097 free(buf);
1098 return IMX_MODEL_MISMATCH;
1099 }
1100 /* load image */
1101 g_debug = opt.debug;
1102 clear_keys();
1103 add_key_list(imx_models[opt.model].keys);
1104 enum sb_error_t err;
1105 struct sb_file_t *sb_file = sb_read_memory(buf + offset, size, false, NULL, generic_std_printf, &err);
1106 if(sb_file == NULL)
1107 {
1108 printf("[ERR] Cannot open firmware as SB file: %d\n", err);
1109 free(buf);
1110 return IMX_FIRST_SB_ERROR + err;
1111 }
1112 /* modify image */
1113 ret = make_boot(sb_file, bootfile, opt);
1114 if(ret == IMX_SUCCESS)
1115 {
1116 /* write image */
1117 ret = sb_write_file(sb_file, outfile, NULL, generic_std_printf);
1118 }
1119 /* cleanup */
1120 sb_free(sb_file);
1121 free(buf);
1122 return ret;
1123}
diff --git a/utils/mkimxboot/mkimxboot.h b/utils/mkimxboot/mkimxboot.h
new file mode 100644
index 0000000000..6bf0415e9c
--- /dev/null
+++ b/utils/mkimxboot/mkimxboot.h
@@ -0,0 +1,116 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
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#ifndef MKIMXBOOT_H
23#define MKIMXBOOT_H
24
25#include <stdbool.h>
26#include <stdint.h>
27#include <sys/types.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33enum imx_error_t
34{
35 IMX_SUCCESS = 0,
36 IMX_ERROR = -1,
37 IMX_OPEN_ERROR = -2,
38 IMX_READ_ERROR = -3,
39 IMX_NO_MATCH = -4,
40 IMX_BOOT_INVALID = -5,
41 IMX_BOOT_MISMATCH = -6,
42 IMX_BOOT_CHECKSUM_ERROR = -7,
43 IMX_DONT_KNOW_HOW_TO_PATCH = -8,
44 IMX_VARIANT_MISMATCH = -9,
45 IMX_WRITE_ERROR = -10,
46 IMX_FIRST_SB_ERROR = -11,
47 IMX_MODEL_MISMATCH = -12,
48};
49
50enum imx_output_type_t
51{
52 IMX_DUALBOOT = 0,
53 IMX_RECOVERY,
54 IMX_SINGLEBOOT,
55 IMX_CHARGE,
56 IMX_ORIG_FW,
57};
58
59/* Supported models */
60enum imx_model_t
61{
62 MODEL_UNKNOWN = 0,
63 MODEL_FUZEPLUS,
64 MODEL_ZENXFI2,
65 MODEL_ZENXFI3,
66 MODEL_ZENXFISTYLE,
67 MODEL_ZENSTYLE, /* Style 100 and Style 300 */
68 MODEL_NWZE370,
69 MODEL_NWZE360,
70 /* Last */
71 MODEL_COUNT
72};
73
74/* Supported firmware variants */
75enum imx_firmware_variant_t
76{
77 VARIANT_DEFAULT = 0,
78 /* For the Creative ZEN X-Fi2 */
79 VARIANT_ZENXFI2_NAND,
80 VARIANT_ZENXFI2_SD,
81 VARIANT_ZENXFI2_RECOVERY,
82 /* For the Creative X-Fi Style */
83 VARIANT_ZENXFISTYLE_RECOVERY,
84 /* For the Creative Zen Style 100/300 */
85 VARIANT_ZENSTYLE_RECOVERY,
86 /* Last */
87 VARIANT_COUNT
88};
89
90struct imx_option_t
91{
92 bool debug;
93 enum imx_model_t model;
94 enum imx_output_type_t output;
95 enum imx_firmware_variant_t fw_variant;
96 const char *force_version; // set to NULL to ignore
97};
98
99/* Print internal information to stdout about device database */
100void dump_imx_dev_info(const char *prefix);
101/* Build a SB image from an input firmware and a bootloader, input firmware
102 * can either be a firmware update or another SB file produced by this tool */
103enum imx_error_t mkimxboot(const char *infile, const char *bootfile,
104 const char *outfile, struct imx_option_t opt);
105/* Compute MD5 sum of an entire file */
106enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16]);
107/* Compute "soft" MD5 sum of a SB file */
108enum imx_error_t compute_soft_md5sum(const char *file, uint8_t soft_md5sum[16]);
109/* Translate error */
110const char *imx_error_to_string(enum imx_error_t err);
111
112#ifdef __cplusplus
113}
114#endif
115#endif
116