diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/mkimxboot | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/mkimxboot')
-rw-r--r-- | utils/mkimxboot/Makefile | 46 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot.c | 293 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot.h | 8 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/Makefile | 48 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/bin2c.c | 140 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/config.h | 26 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/dualboot.c | 323 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/dualboot.lds | 17 | ||||
-rw-r--r-- | utils/mkimxboot/main.c | 289 | ||||
-rw-r--r-- | utils/mkimxboot/md5.c | 246 | ||||
-rw-r--r-- | utils/mkimxboot/md5.h | 25 | ||||
-rw-r--r-- | utils/mkimxboot/mkimxboot.c | 1123 | ||||
-rw-r--r-- | utils/mkimxboot/mkimxboot.h | 116 |
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 | |||
10 | IMXTOOLS_DIR=../../utils/imxtools/sbtools/ | ||
11 | |||
12 | COMPILEFLAGS := -Wall -g -O3 -I$(IMXTOOLS_DIR) | ||
13 | |||
14 | # std=gnu99 is required by MinGW on Windows (c99 is sufficient for Linux / MXE) | ||
15 | CFLAGS += -std=gnu99 $(COMPILEFLAGS) | ||
16 | |||
17 | TOMCRYPT_DIR := ../../utils/tomcrypt | ||
18 | |||
19 | CFLAGS += -I$(TOMCRYPT_DIR)/src/headers | ||
20 | LDOPTS += -lpthread $(TOMCRYPT_DIR)/librbtomcrypt.a | ||
21 | |||
22 | OUTPUT = mkimxboot | ||
23 | |||
24 | # inputs for lib | ||
25 | IMXTOOLS_SOURCES = misc.c sb.c crypto.c crc.c elf.c | ||
26 | LIBSOURCES := dualboot.c mkimxboot.c md5.c \ | ||
27 | $(addprefix $(IMXTOOLS_DIR),$(IMXTOOLS_SOURCES)) | ||
28 | |||
29 | # for now build tomcrypt as part of the lib. | ||
30 | LIBSOURCES += $(addprefix $(TOMCRYPT_DIR),$(TOMCRYPT_SOURCES)) | ||
31 | |||
32 | # inputs for binary only | ||
33 | SOURCES := $(LIBSOURCES) main.c | ||
34 | # dependencies for binary | ||
35 | EXTRADEPS := | ||
36 | |||
37 | include ../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 | |||
44 | librbtomcrypt.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 | |||
5 | unsigned 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 | }; | ||
53 | unsigned 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 | }; | ||
93 | unsigned 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 | }; | ||
131 | unsigned 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 | }; | ||
189 | unsigned 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 | }; | ||
250 | unsigned 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 | |||
3 | extern unsigned char dualboot_fuzeplus[728]; | ||
4 | extern unsigned char dualboot_zenxfi2[608]; | ||
5 | extern unsigned char dualboot_zenxfi3[572]; | ||
6 | extern unsigned char dualboot_nwze370[896]; | ||
7 | extern unsigned char dualboot_nwze360[944]; | ||
8 | extern 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 @@ | |||
1 | CC=gcc | ||
2 | LD=ld | ||
3 | OC=objcopy | ||
4 | PREFIX?=arm-elf-eabi- | ||
5 | IMX233_PATH=../../../firmware/target/arm/imx233 | ||
6 | CFLAGS=-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 | ||
13 | TARGETS=fuzeplus zenxfi2 zenxfi3 nwze370 nwze360 zenxfistyle | ||
14 | OPT_fuzeplus=-DSANSA_FUZEPLUS -DIMX233_SUBTARGET=3780 | ||
15 | OPT_zenxfi2=-DCREATIVE_ZENXFI2 -DIMX233_SUBTARGET=3780 | ||
16 | OPT_zenxfi3=-DCREATIVE_ZENXFI3 -DIMX233_SUBTARGET=3780 | ||
17 | OPT_nwze370=-DSONY_NWZE370 -DIMX233_SUBTARGET=3780 | ||
18 | OPT_nwze360=-DSONY_NWZE360 -DIMX233_SUBTARGET=3780 | ||
19 | OPT_zenxfistyle=-DCREATIVE_ZENXFISTYLE -DIMX233_SUBTARGET=3780 | ||
20 | |||
21 | BOOTOBJS=$(patsubst %, dualboot_%.o, $(TARGETS)) | ||
22 | BOOTBINS=$(patsubst %, dualboot_%.arm-bin, $(TARGETS)) | ||
23 | BOOTELFS=$(patsubst %, dualboot_%.arm-elf, $(TARGETS)) | ||
24 | |||
25 | all: ../dualboot.h ../dualboot.c $(BOOTELFS) | ||
26 | |||
27 | # Dualboot bootloaders | ||
28 | |||
29 | dualboot_%.o: dualboot.c | ||
30 | $(PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.o=%)) -c -o $@ $^ | ||
31 | |||
32 | dualboot_%.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 | |||
44 | bin2c: bin2c.c | ||
45 | $(CC) -o bin2c bin2c.c | ||
46 | |||
47 | clean: | ||
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 | |||
35 | static off_t filesize(int fd) | ||
36 | { | ||
37 | struct stat buf; | ||
38 | |||
39 | fstat(fd,&buf); | ||
40 | return buf.st_size; | ||
41 | } | ||
42 | |||
43 | static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name) | ||
44 | { | ||
45 | int i; | ||
46 | |||
47 | fprintf(fp,"unsigned char %s[%ld] = {",name,len); | ||
48 | |||
49 | for (i=0;i<len;i++) { | ||
50 | if ((i % 16) == 0) { | ||
51 | fprintf(fp,"\n "); | ||
52 | } | ||
53 | if (i == (len-1)) { | ||
54 | fprintf(fp,"0x%02x",buf[i]); | ||
55 | } else if ((i % 16) == 15) { | ||
56 | fprintf(fp,"0x%02x,",buf[i]); | ||
57 | } else { | ||
58 | fprintf(fp,"0x%02x, ",buf[i]); | ||
59 | } | ||
60 | } | ||
61 | fprintf(fp,"\n};\n"); | ||
62 | } | ||
63 | |||
64 | int main (int argc, char* argv[]) | ||
65 | { | ||
66 | char* cname; | ||
67 | int i; | ||
68 | FILE *cfile, *hfile; | ||
69 | char cfilename[256], hfilename[256]; | ||
70 | |||
71 | if (argc < 3) { | ||
72 | fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n"); | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | cname=argv[1]; | ||
77 | |||
78 | snprintf(cfilename,256,"%s.c",cname); | ||
79 | cfile = fopen(cfilename,"w+"); | ||
80 | if (cfile == NULL) { | ||
81 | fprintf(stderr,"Couldn't open %s\n",cfilename); | ||
82 | return 2; | ||
83 | } | ||
84 | |||
85 | snprintf(hfilename,256,"%s.h",cname); | ||
86 | hfile = fopen(hfilename,"w+"); | ||
87 | if (hfile == NULL) { | ||
88 | fprintf(stderr,"Couldn't open %s\n",hfilename); | ||
89 | fclose(cfile); | ||
90 | return 3; | ||
91 | } | ||
92 | |||
93 | fprintf(cfile,"/* Generated by bin2c */\n\n"); | ||
94 | fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename)); | ||
95 | fprintf(hfile,"/* Generated by bin2c */\n\n"); | ||
96 | |||
97 | for(i=0; i < argc - 2; i++) { | ||
98 | unsigned char* buf; | ||
99 | off_t len; | ||
100 | off_t orig_len; | ||
101 | char *ext; | ||
102 | char *array = argv[2+i]; | ||
103 | |||
104 | int fd = open(array,O_RDONLY|O_BINARY); | ||
105 | if (fd < 0) { | ||
106 | fprintf(stderr,"Can not open %s\n",argv[2+i]); | ||
107 | fclose(cfile); | ||
108 | fclose(hfile); | ||
109 | return 4; | ||
110 | } | ||
111 | |||
112 | orig_len = filesize(fd); | ||
113 | /* pad to 32bit */ | ||
114 | len = (orig_len + 3) & ~3; | ||
115 | |||
116 | buf = malloc(len); | ||
117 | if (read(fd,buf,orig_len) < orig_len) { | ||
118 | fprintf(stderr,"Short read, aborting\n"); | ||
119 | return 5; | ||
120 | } | ||
121 | |||
122 | /* pad to 32bit with zeros */ | ||
123 | if (len > orig_len) | ||
124 | memset(buf+orig_len, 0, len-orig_len); | ||
125 | |||
126 | /* remove file extension */ | ||
127 | ext = strchr (array, '.'); | ||
128 | if (ext != NULL) | ||
129 | *ext = '\0'; | ||
130 | write_cfile (buf, len, cfile, array); | ||
131 | fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len); | ||
132 | |||
133 | close(fd); | ||
134 | } | ||
135 | |||
136 | fclose(cfile); | ||
137 | fclose(hfile); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
diff --git a/utils/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 | |||
35 | typedef 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 | ||
42 | enum 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 | ||
49 | enum 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 | |||
60 | static inline int __attribute__((always_inline)) read_gpio(int bank, int pin) | ||
61 | { | ||
62 | return (HW_PINCTRL_DINn(bank) >> pin) & 1; | ||
63 | } | ||
64 | |||
65 | static 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 */ | ||
75 | static 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 | |||
90 | static 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 | |||
98 | static 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) | ||
116 | static 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) | ||
135 | static 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) | ||
153 | static 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) | ||
159 | static 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 | |||
178 | static 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) | ||
204 | static 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 | ||
219 | static int boot_decision(int context) | ||
220 | { | ||
221 | return BOOT_ROCK; | ||
222 | } | ||
223 | #endif | ||
224 | |||
225 | /** | ||
226 | * Context functions | ||
227 | */ | ||
228 | static 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 | */ | ||
247 | static 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 | |||
277 | static 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 | |||
284 | int 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 | |||
320 | int __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 @@ | |||
1 | ENTRY(start) | ||
2 | OUTPUT_FORMAT(elf32-littlearm) | ||
3 | OUTPUT_ARCH(arm) | ||
4 | |||
5 | MEMORY | ||
6 | { | ||
7 | OCRAM : ORIGIN = 0, LENGTH = 0x8000 | ||
8 | } | ||
9 | |||
10 | SECTIONS | ||
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 | |||
28 | struct imx_variant_t | ||
29 | { | ||
30 | const char *name; | ||
31 | enum imx_firmware_variant_t variant; | ||
32 | }; | ||
33 | |||
34 | static 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 | |||
46 | struct model_t | ||
47 | { | ||
48 | const char *name; | ||
49 | enum imx_model_t model; | ||
50 | }; | ||
51 | |||
52 | struct 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 | |||
66 | static 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 | |||
110 | static 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 | |||
135 | int 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 | |||
41 | void 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 | |||
52 | void 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 | |||
175 | void 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 | |||
214 | static 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 | |||
222 | void 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 | |||
12 | typedef struct | ||
13 | { | ||
14 | uint32 total[2]; | ||
15 | uint32 state[4]; | ||
16 | uint8 buffer[64]; | ||
17 | } | ||
18 | md5_context; | ||
19 | |||
20 | void md5_starts( md5_context *ctx ); | ||
21 | void md5_update( md5_context *ctx, uint8 *input, uint32 length ); | ||
22 | void 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. */ | ||
34 | struct 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 */ | ||
43 | struct 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 */ | ||
52 | struct 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 */ | ||
65 | struct 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 */ | ||
88 | static 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 */ | ||
99 | static 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 | |||
202 | static struct crypto_key_t zero_key = | ||
203 | { | ||
204 | .method = CRYPTO_KEY, | ||
205 | .u.key = {0} | ||
206 | }; | ||
207 | |||
208 | static struct crypto_key_t *list_zero_key[] = { &zero_key, NULL }; | ||
209 | static struct crypto_key_t *list_all_keys[] = { &zero_key, NULL }; | ||
210 | |||
211 | static 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 | |||
236 | const 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 | |||
257 | static void add_key_list(struct crypto_key_t **list) | ||
258 | { | ||
259 | while(*list != NULL) | ||
260 | add_keys(*list++, 1); | ||
261 | } | ||
262 | |||
263 | static 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 */ | ||
269 | static 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 | |||
281 | static 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 | |||
423 | static 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 | |||
444 | static 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 | |||
467 | static 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 | |||
516 | static 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 | |||
571 | static 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 | |||
612 | static uint32_t get_uint32be(unsigned char *p) | ||
613 | { | ||
614 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | ||
615 | } | ||
616 | |||
617 | void 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 */ | ||
645 | static 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 */ | ||
680 | static 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 */ | ||
704 | static 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 */ | ||
723 | static 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 */ | ||
733 | static 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 */ | ||
802 | enum 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 */ | ||
815 | enum 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. */ | ||
836 | static 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 | |||
874 | struct elf_user_t | ||
875 | { | ||
876 | void *buf; | ||
877 | size_t sz; | ||
878 | }; | ||
879 | |||
880 | static 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. */ | ||
894 | static 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. */ | ||
945 | static 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. */ | ||
956 | static 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 */ | ||
971 | static 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 | |||
979 | static 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 */ | ||
988 | static 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 | |||
1014 | enum 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 | ||
30 | extern "C" { | ||
31 | #endif | ||
32 | |||
33 | enum 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 | |||
50 | enum 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 */ | ||
60 | enum 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 */ | ||
75 | enum 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 | |||
90 | struct 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 */ | ||
100 | void 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 */ | ||
103 | enum 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 */ | ||
106 | enum imx_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16]); | ||
107 | /* Compute "soft" MD5 sum of a SB file */ | ||
108 | enum imx_error_t compute_soft_md5sum(const char *file, uint8_t soft_md5sum[16]); | ||
109 | /* Translate error */ | ||
110 | const char *imx_error_to_string(enum imx_error_t err); | ||
111 | |||
112 | #ifdef __cplusplus | ||
113 | } | ||
114 | #endif | ||
115 | #endif | ||
116 | |||