summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rbutil/mkzenboot/Makefile30
-rw-r--r--rbutil/mkzenboot/dualboot.c43
-rw-r--r--rbutil/mkzenboot/dualboot.h5
-rw-r--r--rbutil/mkzenboot/dualboot/Makefile50
-rw-r--r--rbutil/mkzenboot/dualboot/bin2c.c140
-rw-r--r--rbutil/mkzenboot/dualboot/config.h22
-rw-r--r--rbutil/mkzenboot/dualboot/dualboot.c134
-rw-r--r--rbutil/mkzenboot/dualboot/dualboot.lds32
-rw-r--r--rbutil/mkzenboot/main.c123
-rw-r--r--rbutil/mkzenboot/md5.c246
-rw-r--r--rbutil/mkzenboot/md5.h25
-rw-r--r--rbutil/mkzenboot/mkzenboot.c689
-rw-r--r--rbutil/mkzenboot/mkzenboot.h86
-rw-r--r--rbutil/mkzenboot/utils.c896
-rw-r--r--rbutil/mkzenboot/utils.h53
15 files changed, 2574 insertions, 0 deletions
diff --git a/rbutil/mkzenboot/Makefile b/rbutil/mkzenboot/Makefile
new file mode 100644
index 0000000000..019b8a669f
--- /dev/null
+++ b/rbutil/mkzenboot/Makefile
@@ -0,0 +1,30 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7
8# We use the HMAC-SHA1 code from tools/
9TOOLS_DIR=../../tools/
10CFLAGS += -Wall -I$(TOOLS_DIR)
11CFLAGS += -std=c99 -g
12LDOPTS += -lz
13
14OUTPUT = mkzenboot
15
16# inputs for lib
17TOOLS_SOURCES = hmac-sha1.c
18LIBSOURCES := dualboot.c mkzenboot.c md5.c utils.c \
19 $(addprefix $(TOOLS_DIR),$(TOOLS_SOURCES))
20
21# inputs for binary only
22SOURCES := $(LIBSOURCES) main.c
23# dependencies for binary
24EXTRADEPS :=
25
26include ../libtools.make
27
28# explicit dependencies on dualboot.{c,h} and mkimxboot.h
29$(OBJDIR)mkzenboot.o: dualboot.h dualboot.c mkzenboot.c mkzenboot.h
30$(OBJDIR)main.o: dualboot.h dualboot.c main.c mkzenboot.h
diff --git a/rbutil/mkzenboot/dualboot.c b/rbutil/mkzenboot/dualboot.c
new file mode 100644
index 0000000000..42baada495
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot.c
@@ -0,0 +1,43 @@
1/* Generated by bin2c */
2
3#include "dualboot.h"
4
5unsigned char dualboot_zenmozaic[168] = {
6 0x10, 0x40, 0x2d, 0xe9, 0x7c, 0x30, 0x9f, 0xe5, 0x00, 0x30, 0x93, 0xe5, 0x78, 0x20, 0x9f, 0xe5,
7 0x00, 0x00, 0x92, 0xe5, 0x74, 0x20, 0x9f, 0xe5, 0x02, 0x11, 0xa0, 0xe3, 0x08, 0x10, 0x82, 0xe5,
8 0x03, 0x11, 0x81, 0xe2, 0x08, 0x10, 0x82, 0xe5, 0xff, 0x14, 0x81, 0xe2, 0x58, 0x10, 0x82, 0xe5,
9 0xc2, 0x14, 0x81, 0xe2, 0x24, 0x10, 0x82, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x18, 0x10, 0x82, 0xe5,
10 0x04, 0x10, 0x82, 0xe5, 0x02, 0x10, 0xa0, 0xe1, 0x10, 0x20, 0x91, 0xe5, 0x01, 0x00, 0x12, 0xe3,
11 0xfc, 0xff, 0xff, 0x0a, 0x34, 0x20, 0x9f, 0xe5, 0x50, 0x20, 0x92, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
12 0x3f, 0x27, 0xc2, 0xe3, 0xa5, 0x2e, 0x42, 0xe2, 0x0a, 0x20, 0x42, 0xe2, 0x63, 0x00, 0x52, 0xe3,
13 0x00, 0x30, 0xa0, 0x93, 0x20, 0x00, 0x83, 0x95, 0x14, 0x20, 0x9f, 0xe5, 0x00, 0x00, 0x92, 0xe5,
14 0x33, 0xff, 0x2f, 0xe1, 0x10, 0x80, 0xbd, 0xe8, 0xa0, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x00, 0x41,
15 0x00, 0x00, 0x05, 0x80, 0xa4, 0x00, 0x00, 0x41, 0xda, 0x00, 0xeb, 0x1c, 0x00, 0x00, 0x00, 0x00,
16 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
17};
18unsigned char dualboot_zenxfi[168] = {
19 0x10, 0x40, 0x2d, 0xe9, 0x7c, 0x30, 0x9f, 0xe5, 0x00, 0x30, 0x93, 0xe5, 0x78, 0x20, 0x9f, 0xe5,
20 0x00, 0x00, 0x92, 0xe5, 0x74, 0x20, 0x9f, 0xe5, 0x02, 0x11, 0xa0, 0xe3, 0x08, 0x10, 0x82, 0xe5,
21 0x03, 0x11, 0x81, 0xe2, 0x08, 0x10, 0x82, 0xe5, 0xff, 0x14, 0x81, 0xe2, 0x58, 0x10, 0x82, 0xe5,
22 0xc2, 0x14, 0x81, 0xe2, 0x24, 0x10, 0x82, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x18, 0x10, 0x82, 0xe5,
23 0x04, 0x10, 0x82, 0xe5, 0x02, 0x10, 0xa0, 0xe1, 0x10, 0x20, 0x91, 0xe5, 0x01, 0x00, 0x12, 0xe3,
24 0xfc, 0xff, 0xff, 0x0a, 0x34, 0x20, 0x9f, 0xe5, 0x50, 0x20, 0x92, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
25 0x3f, 0x27, 0xc2, 0xe3, 0xa5, 0x2e, 0x42, 0xe2, 0x0a, 0x20, 0x42, 0xe2, 0x63, 0x00, 0x52, 0xe3,
26 0x00, 0x30, 0xa0, 0x93, 0x20, 0x00, 0x83, 0x95, 0x14, 0x20, 0x9f, 0xe5, 0x00, 0x00, 0x92, 0xe5,
27 0x33, 0xff, 0x2f, 0xe1, 0x10, 0x80, 0xbd, 0xe8, 0xa0, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x00, 0x41,
28 0x00, 0x00, 0x05, 0x80, 0xa4, 0x00, 0x00, 0x41, 0xda, 0x00, 0xeb, 0x1c, 0x00, 0x00, 0x00, 0x00,
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
30};
31unsigned char dualboot_zen[168] = {
32 0x10, 0x40, 0x2d, 0xe9, 0x7c, 0x30, 0x9f, 0xe5, 0x00, 0x30, 0x93, 0xe5, 0x78, 0x20, 0x9f, 0xe5,
33 0x00, 0x00, 0x92, 0xe5, 0x74, 0x20, 0x9f, 0xe5, 0x02, 0x11, 0xa0, 0xe3, 0x08, 0x10, 0x82, 0xe5,
34 0x03, 0x11, 0x81, 0xe2, 0x08, 0x10, 0x82, 0xe5, 0xff, 0x14, 0x81, 0xe2, 0x58, 0x10, 0x82, 0xe5,
35 0xc2, 0x14, 0x81, 0xe2, 0x24, 0x10, 0x82, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x18, 0x10, 0x82, 0xe5,
36 0x04, 0x10, 0x82, 0xe5, 0x02, 0x10, 0xa0, 0xe1, 0x10, 0x20, 0x91, 0xe5, 0x01, 0x00, 0x12, 0xe3,
37 0xfc, 0xff, 0xff, 0x0a, 0x34, 0x20, 0x9f, 0xe5, 0x50, 0x20, 0x92, 0xe5, 0xff, 0x24, 0xc2, 0xe3,
38 0x3f, 0x27, 0xc2, 0xe3, 0xa5, 0x2e, 0x42, 0xe2, 0x0a, 0x20, 0x42, 0xe2, 0x63, 0x00, 0x52, 0xe3,
39 0x00, 0x30, 0xa0, 0x93, 0x20, 0x00, 0x83, 0x95, 0x14, 0x20, 0x9f, 0xe5, 0x00, 0x00, 0x92, 0xe5,
40 0x33, 0xff, 0x2f, 0xe1, 0x10, 0x80, 0xbd, 0xe8, 0xa0, 0x00, 0x00, 0x41, 0x9c, 0x00, 0x00, 0x41,
41 0x00, 0x00, 0x05, 0x80, 0xa4, 0x00, 0x00, 0x41, 0xda, 0x00, 0xeb, 0x1c, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
43};
diff --git a/rbutil/mkzenboot/dualboot.h b/rbutil/mkzenboot/dualboot.h
new file mode 100644
index 0000000000..c6c2d402d0
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot.h
@@ -0,0 +1,5 @@
1/* Generated by bin2c */
2
3extern unsigned char dualboot_zenmozaic[168];
4extern unsigned char dualboot_zenxfi[168];
5extern unsigned char dualboot_zen[168];
diff --git a/rbutil/mkzenboot/dualboot/Makefile b/rbutil/mkzenboot/dualboot/Makefile
new file mode 100644
index 0000000000..cc8c604f6e
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot/Makefile
@@ -0,0 +1,50 @@
1CC=gcc
2LD=ld
3OC=objcopy
4CROSS_PREFIX=arm-elf-eabi-
5REGS_PATH=../../../firmware/target/arm/imx233/regs
6CFLAGS=-mcpu=arm926ej-s -std=gnu99 -I. -I$(REGS_PATH) -nostdlib -ffreestanding -fomit-frame-pointer -O
7LDFLAGS=
8# Edit the following variables when adding a new target.
9# mkimxboot.c also needs to be edited to refer to these
10# To add a new target x you need to:
11# 1) add x to the list in TARGETS
12# 2) create a variable named OPT_x of the form:
13# OPT_x=target specific defines
14TARGETS=zenmozaic zenxfi zen
15OPT_zenmozaic=-DCREATIVE_ZENMOZAIC -DIMX233_SUBTARGET=3700
16OPT_zenxfi=-DCREATIVE_ZENXFI -DIMX233_SUBTARGET=3700
17OPT_zen=-DCREATIVE_ZEN -DIMX233_SUBTARGET=3700
18
19BOOTLDS=$(patsubst %, dualboot_%.lds, $(TARGETS))
20BOOTOBJS=$(patsubst %, dualboot_%.o, $(TARGETS))
21BOOTBINS=$(patsubst %, dualboot_%.arm-bin, $(TARGETS))
22BOOTELFS=$(patsubst %, dualboot_%.arm-elf, $(TARGETS))
23
24all: ../dualboot.h ../dualboot.c $(BOOTELFS)
25
26# Dualboot bootloaders
27
28dualboot_%.o: dualboot.c
29 $(CROSS_PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.o=%)) -c -o $@ $^
30
31dualboot_%.lds: dualboot.lds
32 $(CROSS_PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.lds=%)) -E -x c - < $< | sed '/#/d' > $@
33
34dualboot_%.arm-elf: dualboot_%.o dualboot_%.lds
35 $(CROSS_PREFIX)$(LD) $(LDFLAGS) -T$(@:dualboot_%.arm-elf=dualboot_%.lds) -o $@ $<
36
37# Rules for the ARM code embedded in mkamsboot - assemble, link, then extract
38# the binary code and finally convert to .h for building in mkamsboot
39
40%.arm-bin: %.arm-elf
41 $(CROSS_PREFIX)$(OC) -O binary $< $@
42
43../dualboot.c ../dualboot.h: $(BOOTBINS) bin2c
44 ./bin2c ../dualboot $(BOOTBINS)
45
46bin2c: bin2c.c
47 $(CC) -o bin2c bin2c.c
48
49clean:
50 rm -f *~ bin2c $(BOOTBINS) $(BOOTOBJS) $(BOOTELFS) $(BOOTLDS)
diff --git a/rbutil/mkzenboot/dualboot/bin2c.c b/rbutil/mkzenboot/dualboot/bin2c.c
new file mode 100644
index 0000000000..b02af88a4d
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot/bin2c.c
@@ -0,0 +1,140 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdio.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <stdlib.h>
29#include <libgen.h>
30
31#ifndef O_BINARY
32#define O_BINARY 0
33#endif
34
35static off_t filesize(int fd)
36{
37 struct stat buf;
38
39 fstat(fd,&buf);
40 return buf.st_size;
41}
42
43static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name)
44{
45 int i;
46
47 fprintf(fp,"unsigned char %s[%ld] = {",name,len);
48
49 for (i=0;i<len;i++) {
50 if ((i % 16) == 0) {
51 fprintf(fp,"\n ");
52 }
53 if (i == (len-1)) {
54 fprintf(fp,"0x%02x",buf[i]);
55 } else if ((i % 16) == 15) {
56 fprintf(fp,"0x%02x,",buf[i]);
57 } else {
58 fprintf(fp,"0x%02x, ",buf[i]);
59 }
60 }
61 fprintf(fp,"\n};\n");
62}
63
64int main (int argc, char* argv[])
65{
66 char* cname;
67 int i;
68 FILE *cfile, *hfile;
69 char cfilename[256], hfilename[256];
70
71 if (argc < 3) {
72 fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n");
73 return 1;
74 }
75
76 cname=argv[1];
77
78 snprintf(cfilename,256,"%s.c",cname);
79 cfile = fopen(cfilename,"w+");
80 if (cfile == NULL) {
81 fprintf(stderr,"Couldn't open %s\n",cfilename);
82 return 2;
83 }
84
85 snprintf(hfilename,256,"%s.h",cname);
86 hfile = fopen(hfilename,"w+");
87 if (hfile == NULL) {
88 fprintf(stderr,"Couldn't open %s\n",hfilename);
89 fclose(cfile);
90 return 3;
91 }
92
93 fprintf(cfile,"/* Generated by bin2c */\n\n");
94 fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename));
95 fprintf(hfile,"/* Generated by bin2c */\n\n");
96
97 for(i=0; i < argc - 2; i++) {
98 unsigned char* buf;
99 off_t len;
100 off_t orig_len;
101 char *ext;
102 char *array = argv[2+i];
103
104 int fd = open(array,O_RDONLY|O_BINARY);
105 if (fd < 0) {
106 fprintf(stderr,"Can not open %s\n",argv[2+i]);
107 fclose(cfile);
108 fclose(hfile);
109 return 4;
110 }
111
112 orig_len = filesize(fd);
113 /* pad to 32bit */
114 len = (orig_len + 3) & ~3;
115
116 buf = malloc(len);
117 if (read(fd,buf,orig_len) < orig_len) {
118 fprintf(stderr,"Short read, aborting\n");
119 return 5;
120 }
121
122 /* pad to 32bit with zeros */
123 if (len > orig_len)
124 memset(buf+orig_len, 0, len-orig_len);
125
126 /* remove file extension */
127 ext = strchr (array, '.');
128 if (ext != NULL)
129 *ext = '\0';
130 write_cfile (buf, len, cfile, array);
131 fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len);
132
133 close(fd);
134 }
135
136 fclose(cfile);
137 fclose(hfile);
138
139 return 0;
140}
diff --git a/rbutil/mkzenboot/dualboot/config.h b/rbutil/mkzenboot/dualboot/config.h
new file mode 100644
index 0000000000..ff59cee710
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot/config.h
@@ -0,0 +1,22 @@
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/** empty, used by register files */
diff --git a/rbutil/mkzenboot/dualboot/dualboot.c b/rbutil/mkzenboot/dualboot/dualboot.c
new file mode 100644
index 0000000000..d0587fa65d
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot/dualboot.c
@@ -0,0 +1,134 @@
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
25typedef unsigned long uint32_t;
26
27// target specific boot decision
28enum boot_t
29{
30 BOOT_STOP, /* power down */
31 BOOT_ROCK, /* boot to Rockbox */
32 BOOT_OF, /* boot to OF */
33};
34
35/**
36 * Helper functions
37 */
38
39static inline int __attribute__((always_inline)) read_gpio(int bank, int pin)
40{
41 return (HW_PINCTRL_DINn(bank) >> pin) & 1;
42}
43
44static inline int __attribute__((always_inline)) read_pswitch(void)
45{
46#if IMX233_SUBTARGET >= 3700
47 return BF_RD(POWER_STS, PSWITCH);
48#else
49 return BF_RD(DIGCTL_STATUS, PSWITCH);
50#endif
51}
52
53/* only works for channels <=7, always divide by 2, never accumulates */
54static inline void __attribute__((always_inline)) setup_lradc(int src)
55{
56 BF_CLR(LRADC_CTRL0, SFTRST);
57 BF_CLR(LRADC_CTRL0, CLKGATE);
58 /* don't bother changing the source, we are early enough at boot so that
59 * channel x is mapped to source x */
60 HW_LRADC_CHn_CLR(src) = BM_OR2(LRADC_CHn, NUM_SAMPLES, ACCUMULATE);
61 BF_SETV(LRADC_CTRL2, DIVIDE_BY_TWO, 1 << src);
62}
63
64#define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x)
65#define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x))
66
67static inline int __attribute__((always_inline)) read_lradc(int src)
68{
69 BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src));
70 BF_SETV(LRADC_CTRL0, SCHEDULE, 1 << src);
71 while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src)));
72 return BF_RDn(LRADC_CHn, src, VALUE);
73}
74
75static inline void __attribute__((noreturn)) power_down()
76{
77 /* power down */
78 HW_POWER_RESET = BM_OR2(POWER_RESET, UNLOCK, PWD);
79 while(1);
80}
81
82/**
83 * Boot decision functions
84 */
85
86#if defined(CREATIVE_ZENMOZAIC) || defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI)
87static enum boot_t boot_decision()
88{
89 setup_lradc(0); // setup LRADC channel 0 to read keys
90 /* make a decision */
91 /* read keys */
92 int val = read_lradc(0);
93 /* if back is pressed, boot to OF
94 * otherwise boot to RB */
95 if(val >= 2650 && val < 2750) // conveniently, all players use the same value
96 return BOOT_OF;
97 return BOOT_ROCK;
98}
99#else
100#warning You should define a target specific boot decision function
101static int boot_decision()
102{
103 return BOOT_ROCK;
104}
105#endif
106
107static int main(uint32_t rb_addr, uint32_t of_addr)
108{
109 switch(boot_decision())
110 {
111 case BOOT_ROCK:
112 return rb_addr;
113 case BOOT_OF:
114 /* fix back the loading address
115 /* NOTE: see mkzenboot for more details */
116 *(uint32_t *)0x20 = of_addr;
117 return 0;
118 case BOOT_STOP:
119 default:
120 power_down();
121 }
122}
123
124/** Glue for the linker mostly */
125
126extern uint32_t of_vector;
127extern uint32_t rb_vector;
128extern uint32_t boot_arg;
129
130void __attribute__((section(".start"))) start()
131{
132 uint32_t addr = main(rb_vector, of_vector);
133 ((void (*)(uint32_t))addr)(boot_arg);
134}
diff --git a/rbutil/mkzenboot/dualboot/dualboot.lds b/rbutil/mkzenboot/dualboot/dualboot.lds
new file mode 100644
index 0000000000..7444a1e427
--- /dev/null
+++ b/rbutil/mkzenboot/dualboot/dualboot.lds
@@ -0,0 +1,32 @@
1ENTRY(start)
2OUTPUT_FORMAT(elf32-littlearm)
3OUTPUT_ARCH(arm)
4
5MEMORY
6{
7 /* keep this consistent with the address in mkzenboot.c */
8#if IMX233_SUBTARGET == 3700
9 RAM : ORIGIN = 0x41000000, LENGTH = 0x8000
10#elif IMX233_SUBTARGET == 3600
11 RAM : ORIGIN = 0x61000000, LENGTH = 0x8000
12#else
13#error define me
14#endif
15}
16
17SECTIONS
18{
19 .text :
20 {
21 *(.start*)
22 *(.text*)
23 . = ALIGN(4);
24 LONG(0x1ceb00da)
25 of_vector = .;
26 . += 4;
27 rb_vector = .;
28 . += 4;
29 boot_arg = .;
30 . += 4;
31 } > RAM
32}
diff --git a/rbutil/mkzenboot/main.c b/rbutil/mkzenboot/main.c
new file mode 100644
index 0000000000..7aef2b76a3
--- /dev/null
+++ b/rbutil/mkzenboot/main.c
@@ -0,0 +1,123 @@
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#include <getopt.h>
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include "mkzenboot.h"
27
28static void usage(void)
29{
30 printf("Usage: mkzenboot [options | file]...\n");
31 printf("Options:\n");
32 printf(" -?/--help Display this message\n");
33 printf(" -i <file> Set input file\n");
34 printf(" -o <file> Set output file\n");
35 printf(" -b <file> Set boot file\n");
36 printf(" -t <type> Set output type\n");
37 printf(" -d/--debug Enable debug output\n");
38 printf("Output types: dualboot, deferred_dualboot, singleboot, recovery\n");
39 printf("By default a dualboot image is built\n");
40 exit(1);
41}
42
43int main(int argc, char *argv[])
44{
45 char *outfile = NULL;
46 char *bootfile = NULL;
47 char *infile = NULL;
48 struct zen_option_t opt;
49 memset(&opt, 0, sizeof(opt));
50
51 if(argc == 1)
52 usage();
53
54 while(1)
55 {
56 static struct option long_options[] =
57 {
58 {"help", no_argument, 0, '?'},
59 {"debug", no_argument, 0, 'd'},
60 {0, 0, 0, 0}
61 };
62
63 int c = getopt_long(argc, argv, "?di:o:b:t:", long_options, NULL);
64 if(c == -1)
65 break;
66 switch(c)
67 {
68 case 'd':
69 opt.debug = true;
70 break;
71 case '?':
72 usage();
73 break;
74 case 'o':
75 outfile = optarg;
76 break;
77 case 'i':
78 infile = optarg;
79 break;
80 case 'b':
81 bootfile = optarg;
82 break;
83 case 't':
84 if(strcmp(optarg, "dualboot") == 0) opt.output = ZEN_DUALBOOT;
85 else if(strcmp(optarg, "mixedboot") == 0) opt.output = ZEN_MIXEDBOOT;
86 else if(strcmp(optarg, "singleboot") == 0) opt.output = ZEN_SINGLEBOOT;
87 else if(strcmp(optarg, "recovery") == 0) opt.output = ZEN_RECOVERY;
88 else
89 {
90 printf("Unknown output type '%s'\n", optarg);
91 return 1;
92 }
93 break;
94 default:
95 abort();
96 }
97 }
98
99 if(!outfile)
100 {
101 printf("You must specify an output file\n");
102 return 1;
103 }
104 if(!bootfile)
105 {
106 printf("You must specify a boot file\n");
107 return 1;
108 }
109 if(!infile)
110 {
111 printf("You must specify an input file\n");
112 return 1;
113 }
114 if(optind != argc)
115 {
116 printf("Extra arguments on command line\n");
117 return 1;
118 }
119
120 enum zen_error_t err = mkzenboot(infile, bootfile, outfile, opt);
121 printf("Result: %d\n", err);
122 return 0;
123}
diff --git a/rbutil/mkzenboot/md5.c b/rbutil/mkzenboot/md5.c
new file mode 100644
index 0000000000..530d8df15a
--- /dev/null
+++ b/rbutil/mkzenboot/md5.c
@@ -0,0 +1,246 @@
1/*
2 * RFC 1321 compliant MD5 implementation
3 *
4 * Copyright (C) 2001-2003 Christophe Devine
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <string.h>
22
23#include "md5.h"
24
25#define GET_UINT32(n,b,i) \
26{ \
27 (n) = ( (uint32) (b)[(i) ] ) \
28 | ( (uint32) (b)[(i) + 1] << 8 ) \
29 | ( (uint32) (b)[(i) + 2] << 16 ) \
30 | ( (uint32) (b)[(i) + 3] << 24 ); \
31}
32
33#define PUT_UINT32(n,b,i) \
34{ \
35 (b)[(i) ] = (uint8) ( (n) ); \
36 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
37 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
38 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
39}
40
41void md5_starts( md5_context *ctx )
42{
43 ctx->total[0] = 0;
44 ctx->total[1] = 0;
45
46 ctx->state[0] = 0x67452301;
47 ctx->state[1] = 0xEFCDAB89;
48 ctx->state[2] = 0x98BADCFE;
49 ctx->state[3] = 0x10325476;
50}
51
52void md5_process( md5_context *ctx, uint8 data[64] )
53{
54 uint32 X[16], A, B, C, D;
55
56 GET_UINT32( X[0], data, 0 );
57 GET_UINT32( X[1], data, 4 );
58 GET_UINT32( X[2], data, 8 );
59 GET_UINT32( X[3], data, 12 );
60 GET_UINT32( X[4], data, 16 );
61 GET_UINT32( X[5], data, 20 );
62 GET_UINT32( X[6], data, 24 );
63 GET_UINT32( X[7], data, 28 );
64 GET_UINT32( X[8], data, 32 );
65 GET_UINT32( X[9], data, 36 );
66 GET_UINT32( X[10], data, 40 );
67 GET_UINT32( X[11], data, 44 );
68 GET_UINT32( X[12], data, 48 );
69 GET_UINT32( X[13], data, 52 );
70 GET_UINT32( X[14], data, 56 );
71 GET_UINT32( X[15], data, 60 );
72
73#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
74
75#define P(a,b,c,d,k,s,t) \
76{ \
77 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
78}
79
80 A = ctx->state[0];
81 B = ctx->state[1];
82 C = ctx->state[2];
83 D = ctx->state[3];
84
85#define F(x,y,z) (z ^ (x & (y ^ z)))
86
87 P( A, B, C, D, 0, 7, 0xD76AA478 );
88 P( D, A, B, C, 1, 12, 0xE8C7B756 );
89 P( C, D, A, B, 2, 17, 0x242070DB );
90 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
91 P( A, B, C, D, 4, 7, 0xF57C0FAF );
92 P( D, A, B, C, 5, 12, 0x4787C62A );
93 P( C, D, A, B, 6, 17, 0xA8304613 );
94 P( B, C, D, A, 7, 22, 0xFD469501 );
95 P( A, B, C, D, 8, 7, 0x698098D8 );
96 P( D, A, B, C, 9, 12, 0x8B44F7AF );
97 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
98 P( B, C, D, A, 11, 22, 0x895CD7BE );
99 P( A, B, C, D, 12, 7, 0x6B901122 );
100 P( D, A, B, C, 13, 12, 0xFD987193 );
101 P( C, D, A, B, 14, 17, 0xA679438E );
102 P( B, C, D, A, 15, 22, 0x49B40821 );
103
104#undef F
105
106#define F(x,y,z) (y ^ (z & (x ^ y)))
107
108 P( A, B, C, D, 1, 5, 0xF61E2562 );
109 P( D, A, B, C, 6, 9, 0xC040B340 );
110 P( C, D, A, B, 11, 14, 0x265E5A51 );
111 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
112 P( A, B, C, D, 5, 5, 0xD62F105D );
113 P( D, A, B, C, 10, 9, 0x02441453 );
114 P( C, D, A, B, 15, 14, 0xD8A1E681 );
115 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
116 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
117 P( D, A, B, C, 14, 9, 0xC33707D6 );
118 P( C, D, A, B, 3, 14, 0xF4D50D87 );
119 P( B, C, D, A, 8, 20, 0x455A14ED );
120 P( A, B, C, D, 13, 5, 0xA9E3E905 );
121 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
122 P( C, D, A, B, 7, 14, 0x676F02D9 );
123 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
124
125#undef F
126
127#define F(x,y,z) (x ^ y ^ z)
128
129 P( A, B, C, D, 5, 4, 0xFFFA3942 );
130 P( D, A, B, C, 8, 11, 0x8771F681 );
131 P( C, D, A, B, 11, 16, 0x6D9D6122 );
132 P( B, C, D, A, 14, 23, 0xFDE5380C );
133 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
134 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
135 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
136 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
137 P( A, B, C, D, 13, 4, 0x289B7EC6 );
138 P( D, A, B, C, 0, 11, 0xEAA127FA );
139 P( C, D, A, B, 3, 16, 0xD4EF3085 );
140 P( B, C, D, A, 6, 23, 0x04881D05 );
141 P( A, B, C, D, 9, 4, 0xD9D4D039 );
142 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
143 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
144 P( B, C, D, A, 2, 23, 0xC4AC5665 );
145
146#undef F
147
148#define F(x,y,z) (y ^ (x | ~z))
149
150 P( A, B, C, D, 0, 6, 0xF4292244 );
151 P( D, A, B, C, 7, 10, 0x432AFF97 );
152 P( C, D, A, B, 14, 15, 0xAB9423A7 );
153 P( B, C, D, A, 5, 21, 0xFC93A039 );
154 P( A, B, C, D, 12, 6, 0x655B59C3 );
155 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
156 P( C, D, A, B, 10, 15, 0xFFEFF47D );
157 P( B, C, D, A, 1, 21, 0x85845DD1 );
158 P( A, B, C, D, 8, 6, 0x6FA87E4F );
159 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
160 P( C, D, A, B, 6, 15, 0xA3014314 );
161 P( B, C, D, A, 13, 21, 0x4E0811A1 );
162 P( A, B, C, D, 4, 6, 0xF7537E82 );
163 P( D, A, B, C, 11, 10, 0xBD3AF235 );
164 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
165 P( B, C, D, A, 9, 21, 0xEB86D391 );
166
167#undef F
168
169 ctx->state[0] += A;
170 ctx->state[1] += B;
171 ctx->state[2] += C;
172 ctx->state[3] += D;
173}
174
175void md5_update( md5_context *ctx, uint8 *input, uint32 length )
176{
177 uint32 left, fill;
178
179 if( ! length ) return;
180
181 left = ctx->total[0] & 0x3F;
182 fill = 64 - left;
183
184 ctx->total[0] += length;
185 ctx->total[0] &= 0xFFFFFFFF;
186
187 if( ctx->total[0] < length )
188 ctx->total[1]++;
189
190 if( left && length >= fill )
191 {
192 memcpy( (void *) (ctx->buffer + left),
193 (void *) input, fill );
194 md5_process( ctx, ctx->buffer );
195 length -= fill;
196 input += fill;
197 left = 0;
198 }
199
200 while( length >= 64 )
201 {
202 md5_process( ctx, input );
203 length -= 64;
204 input += 64;
205 }
206
207 if( length )
208 {
209 memcpy( (void *) (ctx->buffer + left),
210 (void *) input, length );
211 }
212}
213
214static uint8 md5_padding[64] =
215{
216 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
220};
221
222void md5_finish( md5_context *ctx, uint8 digest[16] )
223{
224 uint32 last, padn;
225 uint32 high, low;
226 uint8 msglen[8];
227
228 high = ( ctx->total[0] >> 29 )
229 | ( ctx->total[1] << 3 );
230 low = ( ctx->total[0] << 3 );
231
232 PUT_UINT32( low, msglen, 0 );
233 PUT_UINT32( high, msglen, 4 );
234
235 last = ctx->total[0] & 0x3F;
236 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
237
238 md5_update( ctx, md5_padding, padn );
239 md5_update( ctx, msglen, 8 );
240
241 PUT_UINT32( ctx->state[0], digest, 0 );
242 PUT_UINT32( ctx->state[1], digest, 4 );
243 PUT_UINT32( ctx->state[2], digest, 8 );
244 PUT_UINT32( ctx->state[3], digest, 12 );
245}
246
diff --git a/rbutil/mkzenboot/md5.h b/rbutil/mkzenboot/md5.h
new file mode 100644
index 0000000000..71fa395548
--- /dev/null
+++ b/rbutil/mkzenboot/md5.h
@@ -0,0 +1,25 @@
1#ifndef _MD5_H
2#define _MD5_H
3
4#ifndef uint8
5#define uint8 unsigned char
6#endif
7
8#ifndef uint32
9#define uint32 unsigned long int
10#endif
11
12typedef struct
13{
14 uint32 total[2];
15 uint32 state[4];
16 uint8 buffer[64];
17}
18md5_context;
19
20void md5_starts( md5_context *ctx );
21void md5_update( md5_context *ctx, uint8 *input, uint32 length );
22void md5_finish( md5_context *ctx, uint8 digest[16] );
23
24#endif /* md5.h */
25
diff --git a/rbutil/mkzenboot/mkzenboot.c b/rbutil/mkzenboot/mkzenboot.c
new file mode 100644
index 0000000000..396357e6fe
--- /dev/null
+++ b/rbutil/mkzenboot/mkzenboot.c
@@ -0,0 +1,689 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere
11 * Based on zenutils by Rasmus Ry <rasmus.ry{at}gmail.com>
12 * Copyright (C) 2013 by Amaury Pouly
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include <stdio.h>
24#include <stdlib.h>
25#include <stdarg.h>
26#include <string.h>
27#include "mkzenboot.h"
28#include "utils.h"
29#include "dualboot.h"
30
31/**
32 * Keys used by players
33 */
34static const char null_key_v1[] = "CTL:N0MAD|PDE0.SIGN.";
35static const char null_key_v2[] = "CTL:N0MAD|PDE0.DPMP.";
36static const char null_key_v3[] = "CTL:N0MAD|PDE0.DPFP.";
37static const char null_key_v4[] = "CTL:Z3N07|PDE0.DPMP.";
38
39static const char tl_zvm_key[] = "1sN0TM3D az u~may th1nk*"
40 "Creative Zen Vision:M";
41static const char tl_zvm60_key[] = "1sN0TM3D az u~may th1nk*"
42 "Creative Zen Vision:M (D"
43 "VP-HD0004)";
44static const char tl_zen_key[] = "1sN0TM3D az u~may th1nk*"
45 "Creative ZEN";
46static const char tl_zenxf_key[] = "1sN0TM3D az u~may th1nk*"
47 "Creative ZEN X-Fi";
48static const char tl_zenmo_key[] = "1sN0TM3D az u~may th1nk*"
49 "Creative ZEN Mozaic";
50static const char tl_zv_key[] = "1sN0TM3D az u~may th1nk*"
51 "Creative Zen Vision";
52static const char tl_zvw_key[] = "1sN0TM3D az u~may th1nk*"
53 "Creative ZEN Vision W";
54static const char tl_zm_key[] = "1sN0TM3D az u~may th1nk*"
55 "Creative Zen Micro";
56static const char tl_zmp_key[] = "1sN0TM3D az u~may th1nk*"
57 "Creative Zen MicroPhoto";
58static const char tl_zs_key[] = "1sN0TM3D az u~may th1nk*"
59 "Creative Zen Sleek";
60static const char tl_zsp_key[] = "1sN0TM3D az u~may th1nk*"
61 "Creative Zen Sleek Photo";
62static const char tl_zt_key[] = "1sN0TM3D az u~may th1nk*"
63 "Creative Zen Touch";
64static const char tl_zx_key[] = "1sN0TM3D az u~may th1nk*"
65 "NOMAD Jukebox Zen Xtra";
66static const char tl_zenv_key[] = "1sN0TM3D az u~may th1nk*"
67 "Creative ZEN V";
68static const char tl_zenvp_key[] = "1sN0TM3D az u~may th1nk*"
69 "Creative ZEN V Plus";
70static const char tl_zenvv_key[] = "1sN0TM3D az u~may th1nk*"
71 "Creative ZEN V (Video)";
72
73struct player_info_t
74{
75 const char* name;
76 const char* null_key; /* HMAC-SHA1 key */
77 const char* tl_key; /* BlowFish key */
78 bool big_endian;
79 char *cinf;
80};
81
82static struct player_info_t zen_players[] =
83{
84 {"Zen Vision:M", null_key_v2, tl_zvm_key, false, NULL},
85 {"Zen Vision:M 60GB", null_key_v2, tl_zvm60_key, false, NULL},
86 {"Zen", null_key_v4, tl_zen_key, false, "Creative ZEN"},
87 {"Zen X-Fi", null_key_v4, tl_zenxf_key, false, "Creative ZEN X-Fi"},
88 {"Zen Mozaic", null_key_v4, tl_zenmo_key, false, "Creative ZEN Mozaic"},
89 {"Zen Vision", null_key_v2, tl_zv_key, false, NULL},
90 {"Zen Vision W", null_key_v2, tl_zvw_key, false, NULL},
91 {"Zen Micro", null_key_v1, tl_zm_key, true, NULL},
92 {"Zen MicroPhoto", null_key_v1, tl_zmp_key, true, NULL},
93 {"Zen Sleek", null_key_v1, tl_zs_key, true, NULL},
94 {"Zen SleekPhoto", null_key_v1, tl_zsp_key, true, NULL},
95 {"Zen Touch", null_key_v1, tl_zt_key, true, NULL},
96 {"Zen Xtra", null_key_v1, tl_zx_key, true, NULL},
97 {"Zen V", null_key_v3, tl_zenv_key, false, NULL},
98 {"Zen V Plus", null_key_v3, tl_zenvp_key, false, NULL},
99 {"Zen V Video", null_key_v3, tl_zenvv_key, false, NULL},
100 {NULL, NULL, NULL, false, NULL}
101};
102
103/**
104 * Information on how to patch firmwares
105 */
106struct zen_model_desc_t
107{
108 /* Descriptive name of this model (must match player in zen_players[]) */
109 const char *model_name;
110 /* Model name used in the Rockbox header in ".zen" files - these match the
111 -add parameter to the "scramble" tool */
112 const char *rb_model_name;
113 /* Model number used to initialise the checksum in the Rockbox header in
114 ".zen" files - these are the same as MODEL_NUMBER in config-target.h */
115 const int rb_model_num;
116 /* Bootloader load address */
117 uint32_t bootloader_addr;
118 /* Dualboot code for this model */
119 const unsigned char *dualboot;
120 /* Size of dualboot functions for this model */
121 int dualboot_size;
122};
123
124/* keep this consistent with the address in dualboot.lds */
125static const struct zen_model_desc_t zen_models[] =
126{
127 [MODEL_UNKNOWN] =
128 {
129 "Unknown", " ", 0, 0, NULL, 0
130 },
131 [MODEL_ZENV] =
132 {
133 "Zen V", "zenv", 85, 0x60000000, NULL, 0
134 },
135 [MODEL_ZENXFI] =
136 {
137 "Zen X-Fi", "zxfi", 86, 0x41000000, dualboot_zenxfi, sizeof(dualboot_zenxfi)
138 },
139 [MODEL_ZENMOZAIC] =
140 {
141 "Zen Mozaic", "zmoz", 87, 0x41000000, dualboot_zenmozaic, sizeof(dualboot_zenmozaic)
142 },
143 [MODEL_ZEN] =
144 {
145 "Zen", "zen", 90, 0x41000000, dualboot_zen, sizeof(dualboot_zen)
146 },
147};
148
149/**
150 * MD5 knowledge base
151 */
152
153struct zen_md5sum_t
154{
155 /* Device model */
156 enum zen_model_t model;
157 /* md5sum of the file */
158 char *md5sum;
159 /* Version string */
160 const char *version;
161};
162
163static const struct zen_md5sum_t zen_sums[] =
164{
165 /** Zen Mozaic */
166 {
167 /* Version 1.06.01e */
168 MODEL_ZENMOZAIC, "88a856f8273b2bc3fcacf1f067a44aa8", "1.06.01e"
169 },
170 /** Zen X-Fi */
171 {
172 /* Version 1.04.08e */
173 MODEL_ZENXFI, "f07e2e75069289a2aa14c6583bd9643b", "1.04.08e"
174 },
175 /** Zen V */
176 {
177 /* Version 1.32.01e */
178 MODEL_ZENV, "2f6d3e619557583c30132ac87221bc3e", "1.32.01e"
179 },
180 /** Zen */
181 {
182 /* Version 1.21.03e */
183 MODEL_ZEN, "1fe28f587f87ac3c280281db28c42465", "1.21.03e"
184 }
185};
186
187#define NR_ZEN_PLAYERS (sizeof(zen_players) / sizeof(zen_players[0]))
188#define NR_ZEN_SUMS (sizeof(zen_sums) / sizeof(zen_sums[0]))
189#define NR_ZEN_MODELS (sizeof(zen_models) / sizeof(zen_models[0]))
190
191#define MAGIC_ROCK 0x726f636b /* 'rock' */
192#define MAGIC_RECOVERY 0xfee1dead
193#define MAGIC_NORMAL 0xcafebabe
194
195/**
196 * Stolen from various places in our codebase
197 */
198
199/**
200 * EDOC file format
201 */
202struct edoc_header_t
203{
204 char magic[4];
205 uint32_t total_size;
206 uint32_t zero;
207};
208
209struct edoc_section_header_t
210{
211 uint32_t addr;
212 uint32_t size;
213 uint32_t checksum;
214};
215
216uint32_t edoc_checksum(void *buffer, size_t size)
217{
218 uint32_t c = 0;
219 uint32_t *p = buffer;
220 while(size >= 4)
221 {
222 c += *p + (*p >> 16);
223 p++;
224 size -= 4;
225 }
226 if(size != 0)
227 printf("[WARN] EDOC Checksum section size is not a multiple of 4 bytes, result is undefined!\n");
228 return c & 0xffff;
229}
230
231#define errorf(err, ...) do { printf(__VA_ARGS__); return err; } while(0)
232
233/**
234 * How does patching code work
235 * ---------------------------
236 *
237 * All Creative firmwares work the same: they start at 0 and the code sequence at
238 * 0 always contains the vector table with ldr with offsets:
239 * 0: e59ff018 ldr pc, [pc, #24] ; 0x20
240 * 4: e59ff018 ldr pc, [pc, #24] ; 0x24
241 * 8: e59ff018 ldr pc, [pc, #24] ; 0x28
242 * c: e59ff018 ldr pc, [pc, #24] ; 0x2c
243 * 10: e59ff018 ldr pc, [pc, #24] ; 0x30
244 * 14: e59ff018 ldr pc, [pc, #24] ; 0x34
245 * 18: e59ff018 ldr pc, [pc, #24] ; 0x38
246 * 1c: e59ff018 ldr pc, [pc, #24] ; 0x3c
247 * 20: 0000dbd4 .word start
248 * 24: 0000dcac .word undef_instr_handler
249 * 28: 0000dcb0 .word software_int_handler
250 * 2c: 0000dcb4 .word prefetch_abort_handler
251 * 30: 0000dcb8 .word data_abort_handler
252 * 34: 0000dcbc .word reserved_handler
253 * 38: 0000dcc0 .word irq_handler
254 * 3c: 0000dd08 .word fiq_handler
255 *
256 * To build a dual-boot image, we modify the start address to point to some
257 * code we added to the image. Specifically we first add the stub, then
258 * the rockbox image. We also write the old start address to this
259 * stub so that it can either decide to run rockbox or patch back the
260 * start address and jump to 0.
261 * Singleboot and recovery is handled the same way except that both targets use
262 * the same address and we drop the OF, so we create a fake vector table!
263 */
264
265struct dualboot_footer_t
266{
267 uint32_t magic;
268 uint32_t of_addr;
269 uint32_t rb_addr;
270 uint32_t boot_arg;
271} __attribute__((packed));
272
273#define FOOTER_MAGIC 0x1ceb00da
274
275static enum zen_error_t create_fake_image(uint8_t **fw, uint32_t *fw_size)
276{
277 /** We need to create a fake EDOC image, so first a header and one section
278 * header with one data chunk. */
279 /** The fake image is as follows:
280 * 0: e59ff018 ldr pc, [pc, #24] ; 0x20
281 * 4: e59ff018 ldr pc, [pc, #24] ; 0x24
282 * 8: e59ff018 ldr pc, [pc, #24] ; 0x28
283 * c: e59ff018 ldr pc, [pc, #24] ; 0x2c
284 * 10: e59ff018 ldr pc, [pc, #24] ; 0x30
285 * 14: e59ff018 ldr pc, [pc, #24] ; 0x34
286 * 18: e59ff018 ldr pc, [pc, #24] ; 0x38
287 * 1c: e59ff018 ldr pc, [pc, #24] ; 0x3c
288 * 20: 00000040 .word hang
289 * 24: 00000040 .word hang
290 * 28: 00000040 .word hang
291 * 2c: 00000040 .word hang
292 * 30: 00000040 .word hang
293 * 34: 00000040 .word hang
294 * 38: 00000040 .word hang
295 * 3c: 00000040 .word hang
296 * 40 <hang>:
297 * 40: eafffffe b 40 <hang> */
298 *fw_size = sizeof(struct edoc_header_t) + sizeof(struct edoc_section_header_t) + 0x44;
299 *fw = malloc(*fw_size);
300 if(*fw == NULL)
301 errorf(ZEN_ERROR, "[ERR] Allocation failed");
302 struct edoc_header_t *hdr = (void *)*fw;
303 memcpy(hdr->magic, "EDOC", 4);
304 hdr->total_size = *fw_size - sizeof(struct edoc_header_t) + 4;
305 hdr->zero = 0;
306 struct edoc_section_header_t *sec = (void *)(hdr + 1);
307 sec->addr = 0;
308 sec->size = 0x44;
309 uint32_t *p = (void *)(sec + 1);
310 p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0xe59ff018;
311 p[8] = p[9] = p[10] = p[11] = p[12] = p[13] = p[14] = p[15] = 0x40;
312 p[16] = 0xeafffffe;
313 sec->checksum = edoc_checksum(p, 0x44);
314 return ZEN_SUCCESS;
315}
316
317static enum zen_error_t patch_firmware(uint8_t **fw, uint32_t *fw_size,
318 void *boot, size_t boot_size, struct zen_option_t opt)
319{
320 /* check if dualboot stub is available */
321 const void *dualboot = zen_models[opt.model].dualboot;
322 int dualboot_size = zen_models[opt.model].dualboot_size;
323 uint32_t dualboot_addr = zen_models[opt.model].bootloader_addr;
324 if(dualboot == NULL)
325 errorf(ZEN_DONT_KNOW_HOW_TO_PATCH, "[ERR] I don't have a dualboot stub for this model\n");
326 /* if not asked to dualboot, drop OF and create a fake image */
327 if(opt.output != ZEN_DUALBOOT)
328 {
329 enum zen_error_t ret = create_fake_image(fw, fw_size);
330 if(ret != ZEN_SUCCESS)
331 return ret;
332 }
333 /* compute final image size: add stub + bootloader in one block as a section */
334 int extra_size = sizeof(struct edoc_section_header_t) + dualboot_size + boot_size;
335 *fw_size += extra_size;
336 *fw = realloc(*fw, *fw_size);
337 if(*fw == NULL)
338 errorf(ZEN_ERROR, "[ERR] Allocation failed");
339 /* sanity check */
340 struct edoc_header_t *hdr = (void *)*fw;
341 if(memcmp(hdr->magic, "EDOC", 4) != 0)
342 errorf(ZEN_FW_INVALID, "[ERR] Firmware doesn't use EDOC format\n");
343 /* validate image and find OF start addr */
344 uint32_t of_addr = 0;
345 struct edoc_section_header_t *sec_hdr = (void *)(hdr + 1);
346 while((void *)sec_hdr - (void *)&hdr->zero < hdr->total_size)
347 {
348 if(sec_hdr->checksum != edoc_checksum(sec_hdr + 1, sec_hdr->size))
349 errorf(ZEN_FW_INVALID, "[ERR] Firmware checksum error\n");
350 if(sec_hdr->addr == 0)
351 {
352 uint32_t *start_vector = ((void *)(sec_hdr + 1) + 0x20);
353 /* extract address */
354 of_addr = *(uint32_t *)start_vector;
355 /* patch vector */
356 *start_vector = dualboot_addr;
357 /* fix checksum */
358 sec_hdr->checksum = edoc_checksum(sec_hdr + 1, sec_hdr->size);
359 }
360 sec_hdr = (void *)(sec_hdr + 1) + sec_hdr->size;
361 }
362 if(of_addr == 0)
363 errorf(ZEN_FW_INVALID, "[ERR] Firmware doesn't have the expected format\n");
364 printf("[INFO] OF start address: %#x\n", of_addr);
365 /* add extra section */
366 sec_hdr->addr = dualboot_addr;
367 sec_hdr->size = dualboot_size + boot_size;
368 /* add extra data */
369 memcpy(sec_hdr + 1, dualboot, dualboot_size);
370 memcpy((void *)(sec_hdr + 1) + dualboot_size, boot, boot_size);
371 /* locate and patch dualboot footer */
372 struct dualboot_footer_t *footer = (void *)(sec_hdr + 1) + dualboot_size -
373 sizeof(struct dualboot_footer_t);
374 if(footer->magic != FOOTER_MAGIC)
375 errorf(ZEN_FW_INVALID, "[ERR] Footer magic mismatch\n");
376 uint32_t rb_addr = dualboot_addr + dualboot_size;
377 printf("[INFO] RB start address: %#x\n", rb_addr);
378 footer->of_addr = opt.output == ZEN_DUALBOOT ? of_addr : rb_addr;
379 footer->rb_addr = rb_addr;
380 footer->boot_arg = opt.output == ZEN_RECOVERY ? 0xfee1dead : 0xcafebabe;
381 printf("[INFO] Footer: 0x%08x 0x%08x 0x%08x\n", footer->of_addr, footer->rb_addr,
382 footer->boot_arg);
383 /* fix image */
384 sec_hdr->checksum = edoc_checksum(sec_hdr + 1, sec_hdr->size);
385 hdr->total_size += extra_size;
386 return ZEN_SUCCESS;
387}
388
389struct player_info_t *get_player_info(enum zen_model_t model)
390{
391 for(int i = 0; zen_players[i].name; i++)
392 if(strcmp(zen_models[model].model_name, zen_players[i].name) == 0)
393 return &zen_players[i];
394 return NULL;
395}
396
397enum zen_error_t build_firmware(void *exec, size_t exec_size, void *boot, size_t boot_size,
398 const char *outfile, struct zen_option_t opt)
399{
400 uint8_t *buffer = exec;
401 /** find player info */
402 struct player_info_t *player = get_player_info(opt.model);
403 if(player == NULL)
404 errorf(ZEN_UNSUPPORTED, "[ERR] There is no player info for this model\n");
405 if(player->big_endian)
406 errorf(ZEN_UNSUPPORTED, "[ERR] Big-endian players are currently unsupported\n");
407
408 /** Find Win32 PE .data section */
409 uint32_t data_ptr;
410 uint32_t data_size;
411 enum zen_error_t err = find_pe_data(exec, exec_size, &data_ptr, &data_size);
412 if(err != ZEN_SUCCESS)
413 errorf(err, "[ERR] Cannot find .data section\n");
414 printf("[INFO] .data section is at 0x%x with size 0x%x\n", data_ptr, data_size);
415
416 /** look for firmware and key in data section */
417 uint32_t fw_offset = find_firmware_offset(&buffer[data_ptr], data_size);
418 if(fw_offset == 0)
419 errorf(ZEN_FW_INVALID, "[ERR] Couldn't find firmware offset\n");
420 uint32_t fw_size = le2int(&buffer[data_ptr + fw_offset]);
421 printf("[INFO] Firmware offset is at 0x%x with size 0x%x\n", data_ptr + fw_offset, fw_size);
422 const char *fw_key = find_firmware_key(exec, exec_size);
423 if(fw_key == NULL)
424 errorf(ZEN_FW_INVALID, "[ERR] Couldn't find firmware key\n");
425 printf("[INFO] Firmware key is %s\n", fw_key);
426
427 /** descramble firmware */
428 printf("[INFO] Descrambling firmware... ");
429 if(!crypt_firmware(fw_key, &buffer[data_ptr + fw_offset + 4], fw_size))
430 errorf(ZEN_ERROR, "Fail!\n");
431 else
432 printf("Done!\n");
433 /** decompress it */
434 uint8_t *out_buffer = malloc(fw_size * 2);
435 if(out_buffer == NULL)
436 errorf(ZEN_ERROR, "[ERR] Couldn't allocate memory");
437 memset(out_buffer, 0, fw_size * 2);
438 printf("[INFO] Decompressing firmware... ");
439 char *err_msg;
440 if(!inflate_to_buffer(&buffer[data_ptr + fw_offset + 4], fw_size, out_buffer,
441 fw_size * 2, &err_msg))
442 errorf(ZEN_ERROR, "Fail!\n[ERR] ZLib error: %s\n", err_msg);
443 else
444 printf("Done!\n");
445
446 /** check format and resize the buffer */
447 if(memcmp(out_buffer, "FFIC", 4) != 0)
448 errorf(ZEN_FW_INVALID, "[ERR] CIFF header doesn't match\n");
449 uint32_t ciff_size = le2int(&out_buffer[4]) + 8 + 28; /* CIFF block + NULL block*/
450 printf("[INFO] Total firmware size: %d\n", ciff_size);
451 out_buffer = realloc(out_buffer, ciff_size);
452 if(out_buffer == NULL)
453 errorf(ZEN_ERROR, "[ERR] Cannot resize memory block\n");
454
455 /** look for firmware file */
456 printf("[INFO] Locating encoded block... ");
457 uint32_t fw_off = 8;
458 uint8_t *cinf_ptr = NULL;
459 while(memcmp(&out_buffer[fw_off], " LT\xa9", 4) != 0 && fw_off < ciff_size)
460 {
461 if(memcmp(&out_buffer[fw_off], "FNIC", 4) == 0)
462 {
463 cinf_ptr = &out_buffer[fw_off + 8];
464 fw_off += 4 + 4 + 96;
465 }
466 else if(memcmp(&out_buffer[fw_off], "ATAD", 4) == 0)
467 {
468 fw_off += 4;
469 fw_off += le2int(&out_buffer[fw_off]);
470 fw_off += 4;
471 }
472 else
473 errorf(ZEN_FW_INVALID, "Fail!\n[ERR] Unknown block\n");
474 }
475 if(fw_off >= ciff_size || memcmp(&out_buffer[fw_off], " LT\xa9", 4) != 0)
476 errorf(ZEN_FW_INVALID, "Fail!\n[ERR] Couldn't find encoded block\n");
477 if(!cinf_ptr)
478 errorf(ZEN_FW_INVALID, "Fail!\n[ERR] Couldn't find CINF\n");
479 printf("Done!\n");
480
481 /** validate player if possible */
482 printf("[INFO] Checking player model...");
483 if(player->cinf)
484 {
485 char cinf_ascii[96];
486 for(int j = 0; j < 96; j++)
487 cinf_ascii[j] = *(unsigned short *)&cinf_ptr[2 * j];
488 if(strncmp(cinf_ascii, player->cinf, 96) != 0)
489 errorf(ZEN_FW_MISMATCH, "Fail!\n[ERR] Player mismatch: CINF indicates '%s' instead of '%s'\n",
490 cinf_ascii, player->cinf);
491 else
492 printf("Done!\n");
493 }
494 else
495 printf("Bypass!\n");
496
497 /** decrypt firmware */
498 printf("[INFO] Decrypting encoded block... ");
499 uint32_t iv[2];
500 iv[0] = 0;
501 iv[1] = swap(le2int(&out_buffer[fw_off + 4]));
502 if(!bf_cbc_decrypt((unsigned char*)player->tl_key, strlen(player->tl_key) + 1,
503 &out_buffer[fw_off + 8], le2int(&out_buffer[fw_off + 4]), (const unsigned char*)&iv))
504 errorf(ZEN_ERROR, "Fail!\n[ERR] Couldn't decrypt encoded block\n");
505 printf("Done!\n");
506
507 /** sanity checks on firmware */
508 uint32_t jrm_size = le2int(&out_buffer[fw_off + 8]);
509 if(jrm_size > le2int(&out_buffer[fw_off + 4]) * 3)
510 errorf(ZEN_FW_INVALID, "[ERR] Decrypted length of encoded block is unexpectedly large: 0x%08x\n", jrm_size);
511 printf("[INFO] Firmware size: %d\n", jrm_size);
512 uint8_t *jrm = malloc(jrm_size);
513 if(jrm == NULL)
514 errorf(ZEN_ERROR, "[ERR] Couldn't allocate memory\n");
515 memset(buffer, 0, jrm_size);
516
517 /** decompress firmware */
518 printf("[INFO] Decompressing encoded block... ");
519 if(!cenc_decode(&out_buffer[fw_off + 12], le2int(&out_buffer[fw_off + 4]) - 4, jrm, jrm_size))
520 errorf(ZEN_ERROR, "Fail!\n[ERR] Couldn't decompress the encoded block\n");
521 printf("Done!\n");
522
523 /** Copy OF because patching might modify it */
524 void *jrm_save = malloc(jrm_size);
525 uint32_t jrm_save_size = jrm_size;
526 if(jrm_save == NULL)
527 errorf(ZEN_ERROR, "[ERR] Couldn't allocate memory");
528 memcpy(jrm_save, jrm, jrm_size);
529
530 /** Patch firmware */
531 err = patch_firmware(&jrm, &jrm_size, boot, boot_size, opt);
532 if(err != ZEN_SUCCESS)
533 errorf(err, "[ERR] Couldn't patch firmware\n");
534
535 /** Rebuild archive */
536 bool keep_old_bits = opt.output == ZEN_DUALBOOT || opt.output == ZEN_MIXEDBOOT;
537 bool keep_of = opt.output == ZEN_MIXEDBOOT;
538 /* if we keep old stuff, keep everything up to LT block, otherwise just CIFF header */
539 uint32_t off = keep_old_bits ? fw_off : 8;
540 /* move the rest of the archive if keeping old stuff */
541 if(keep_old_bits)
542 {
543 uint32_t copy_off = fw_off + 8 + le2int(&out_buffer[fw_off + 4]);
544 uint32_t copy_size = ciff_size - fw_off - 8 - le2int(&out_buffer[fw_off + 4]) - 28;
545 memmove(&out_buffer[off], &out_buffer[copy_off], copy_size);
546 off += copy_size;
547 }
548 /* if we keep the OF, put a copy of it after renaming it to Hcreativeos.jrm */
549 if(keep_of)
550 {
551 out_buffer = realloc(out_buffer, off + jrm_save_size + 40);
552 if(out_buffer == NULL)
553 errorf(ZEN_ERROR, "[ERR] Couldn't resize memory block\n");
554 printf("[INFO] Renaming encoded block to Hcreativeos.jrm... ");
555 memcpy(&out_buffer[off], "ATAD", 4);
556 int2le(jrm_save_size + 32, &out_buffer[off + 4]);
557 memset(&out_buffer[off + 8], 0, 32);
558 memcpy(&out_buffer[off + 8], "H\0c\0r\0e\0a\0t\0i\0v\0e\0o\0s\0.\0j\0r\0m", 30);
559 memcpy(&out_buffer[off + 40], jrm_save, jrm_save_size);
560 off += jrm_save_size + 40;
561 printf("Done!\n");
562 }
563 /* put modified firmware */
564 out_buffer = realloc(out_buffer, off + jrm_size + 40);
565 if(out_buffer == NULL)
566 errorf(ZEN_ERROR, "[ERR] Couldn't resize memory block\n");
567 printf("[INFO] Adding Hjukebox2.jrm... ");
568 memcpy(&out_buffer[off], "ATAD", 4);
569 int2le(jrm_size + 32, &out_buffer[off + 4]);
570 memset(&out_buffer[off + 8], 0, 32);
571 memcpy(&out_buffer[off + 8], "H\0j\0u\0k\0e\0b\0o\0x\0""2\0.\0j\0r\0m", 26);
572 memcpy(&out_buffer[off + 40], jrm, jrm_size);
573 off += jrm_size + 40;
574 printf("Done!\n");
575
576 /** fix header */
577 int2le(off - 8, &out_buffer[4]);
578
579 /** update checksum */
580 printf("[INFO] Updating checksum... ");
581 out_buffer = realloc(out_buffer, off + 28);
582 if(out_buffer == NULL)
583 errorf(ZEN_ERROR, "[ERR] Couldn't resize memory block\n");
584 memcpy(&out_buffer[off], "LLUN", 4);
585 int2le(20, &out_buffer[off + 4]);
586 hmac_sha1((unsigned char*)player->null_key, strlen(player->null_key), out_buffer,
587 off, &out_buffer[off + 8]);
588 off += 28;
589 printf("Done!\n");
590
591 err = write_file(outfile, out_buffer, off);
592
593 free(jrm);
594 free(jrm_save);
595 free(out_buffer);
596 return err;
597}
598
599/* find an entry into zen_sums which matches the MD5 sum of a file */
600static enum zen_error_t find_model_by_md5sum(uint8_t file_md5sum[16], int *md5_idx)
601{
602 int i = 0;
603 while(i < NR_ZEN_SUMS)
604 {
605 uint8_t md5[20];
606 if(strlen(zen_sums[i].md5sum) != 32)
607 errorf(ZEN_ERROR, "[ERR][INTERNAL] Invalid MD5 sum in zen_sums\n");
608 for(int j = 0; j < 16; j++)
609 {
610 uint8_t a, b;
611 if(convxdigit(zen_sums[i].md5sum[2 * j], &a) || convxdigit(zen_sums[i].md5sum[2 * j + 1], &b))
612 errorf(ZEN_ERROR, "[ERR][INTERNAL] Bad checksum format: %s\n", zen_sums[i].md5sum);
613 md5[j] = (a << 4) | b;
614 }
615 if(memcmp(file_md5sum, md5, 16) == 0)
616 break;
617 i++;
618 }
619 if(i == NR_ZEN_SUMS)
620 errorf(ZEN_NO_MATCH, "[ERR] MD5 sum doesn't match any known file\n");
621 *md5_idx = i;
622 return ZEN_SUCCESS;
623}
624
625enum zen_error_t mkzenboot(const char *infile, const char *bootfile,
626 const char *outfile, struct zen_option_t opt)
627{
628 /* determine firmware model */
629 void *fw;
630 size_t fw_size;
631 enum zen_error_t err = read_file(infile, &fw, &fw_size);
632 uint8_t file_md5sum[16];
633 err = compute_md5sum_buf(fw, fw_size, file_md5sum);
634 if(err != ZEN_SUCCESS)
635 {
636 free(fw);
637 return err;
638 }
639 printf("[INFO] MD5 sum of the file: ");
640 for(int i = 0; i < 16; i++)
641 printf("%02X ", file_md5sum[i]);
642 printf("\n");
643 if(opt.model == MODEL_UNKNOWN)
644 {
645 int idx;
646 err = find_model_by_md5sum(file_md5sum, &idx);
647 if(err != ZEN_SUCCESS)
648 {
649 free(fw);
650 errorf(err, "[ERR] Cannot determine model type\n");
651 }
652 opt.model = zen_sums[idx].model;
653 printf("[INFO] MD5 matches %s, version %s\n",
654 zen_models[opt.model].model_name, zen_sums[idx].version);
655 }
656 printf("[INFO] Model is: %s\n", zen_models[opt.model].model_name);
657 /* load rockbox file */
658 uint8_t *boot;
659 size_t boot_size;
660 err = read_file(bootfile, (void **)&boot, &boot_size);
661 if(err != ZEN_SUCCESS)
662 {
663 free(fw);
664 errorf(err, "[ERR] Cannot read boot file\n");
665 }
666 /* validate checksum */
667 if(memcmp(boot + 4, zen_models[opt.model].rb_model_name, 4) != 0)
668 {
669 free(fw);
670 free(boot);
671 errorf(ZEN_BOOT_MISMATCH, "[ERR] Boot model mismatch\n");
672 }
673 printf("[INFO] Bootloader file matches model\n");
674 uint32_t sum = zen_models[opt.model].rb_model_num;
675 for(int i = 8; i < boot_size; i++)
676 sum += boot[i];
677 if(sum != be2int(boot))
678 {
679 free(fw);
680 free(boot);
681 errorf(ZEN_BOOT_CHECKSUM_ERROR, "[ERR] Checksum mismatch\n");
682 }
683 printf("[INFO] Bootloader file checksum is correct\n");
684 /* produce file */
685 err = build_firmware(fw, fw_size, boot + 8, boot_size - 8, outfile, opt);
686 free(boot);
687 free(fw);
688 return err;
689}
diff --git a/rbutil/mkzenboot/mkzenboot.h b/rbutil/mkzenboot/mkzenboot.h
new file mode 100644
index 0000000000..8da3e25762
--- /dev/null
+++ b/rbutil/mkzenboot/mkzenboot.h
@@ -0,0 +1,86 @@
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#ifndef MKZENBOOT_H
23#define MKZENBOOT_H
24
25#include <stdbool.h>
26#include <stdint.h>
27#include <sys/types.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33enum zen_error_t
34{
35 ZEN_SUCCESS = 0,
36 ZEN_ERROR = -1,
37 ZEN_OPEN_ERROR = -2,
38 ZEN_READ_ERROR = -3,
39 ZEN_NO_MATCH = -4,
40 ZEN_BOOT_INVALID = -5,
41 ZEN_BOOT_MISMATCH = -6,
42 ZEN_BOOT_CHECKSUM_ERROR = -7,
43 ZEN_DONT_KNOW_HOW_TO_PATCH = -8,
44 ZEN_WRITE_ERROR = -9,
45 ZEN_UNSUPPORTED = 10,
46 ZEN_FW_INVALID = -11,
47 ZEN_FW_MISMATCH = -12,
48 ZEN_FIRST_ZENTOOLS_ERROR = -12,
49};
50
51enum zen_output_type_t
52{
53 ZEN_DUALBOOT = 0, /* keep all OF data and pack OF+RB into firmware for dualboot */
54 ZEN_MIXEDBOOT, /* rename OF, keep data, put RB as firmware, use RB bootloader to dualboot */
55 ZEN_RECOVERY, /* only put rockbox with recovery mode */
56 ZEN_SINGLEBOOT, /* only put rockbox with recovery mode */
57};
58
59/* Supported models */
60enum zen_model_t
61{
62 MODEL_UNKNOWN = 0,
63 MODEL_ZENMOZAIC,
64 MODEL_ZENV,
65 MODEL_ZENXFI,
66 MODEL_ZEN,
67 /* new models go here */
68
69 NUM_MODELS
70};
71
72struct zen_option_t
73{
74 bool debug;
75 enum zen_output_type_t output;
76 enum zen_model_t model; /* pass MODEL_UNKNOWN to use MD5 knowledge base */
77};
78
79enum zen_error_t mkzenboot(const char *infile, const char *bootfile,
80 const char *outfile, struct zen_option_t opt);
81
82#ifdef __cplusplus
83}
84#endif
85#endif
86
diff --git a/rbutil/mkzenboot/utils.c b/rbutil/mkzenboot/utils.c
new file mode 100644
index 0000000000..b8ef3be237
--- /dev/null
+++ b/rbutil/mkzenboot/utils.c
@@ -0,0 +1,896 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Maurus Cuelenaere
11 * Based on zenutils by Rasmus Ry <rasmus.ry{at}gmail.com>
12 * Copyright (C) 2013 by Amaury Pouly
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "utils.h"
24#include "md5.h"
25#include <zlib.h>
26//#include "hmac-sha1.h"
27
28int filesize(FILE* fd)
29{
30 int tmp, tmp2 = ftell(fd);
31 fseek(fd, 0, SEEK_END);
32 tmp = ftell(fd);
33 fseek(fd, tmp2, SEEK_SET);
34 return tmp;
35}
36
37unsigned int le2int(unsigned char* buf)
38{
39 return ((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]);
40}
41
42unsigned int be2int(unsigned char* buf)
43{
44 return ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
45}
46
47void int2le(unsigned int val, unsigned char* addr)
48{
49 addr[0] = val & 0xFF;
50 addr[1] = (val >> 8) & 0xff;
51 addr[2] = (val >> 16) & 0xff;
52 addr[3] = (val >> 24) & 0xff;
53}
54
55const char* find_firmware_key(const unsigned char* buffer, size_t len)
56{
57 char szkey1[] = "34d1";
58 size_t cchkey1 = strlen(szkey1);
59 char szkey2[] = "TbnCboEbn";
60 size_t cchkey2 = strlen(szkey2);
61 uint32_t i;
62 for (i = 0; i < (uint32_t)len; i++)
63 {
64 if (len >= cchkey1)
65 {
66 if (!strncmp((char*)&buffer[i], szkey1, cchkey1))
67 return (const char*)&buffer[i];
68 }
69 if (len >= cchkey2)
70 {
71 if (!strncmp((char*)&buffer[i], szkey2, cchkey2))
72 return (const char*)&buffer[i];
73 }
74 }
75 return NULL;
76}
77
78uint32_t find_firmware_offset(unsigned char* buffer, size_t len)
79{
80 uint32_t i;
81 for (i = 0; i < (uint32_t)len; i += 0x10)
82 {
83 if (buffer[i + sizeof(uint32_t)] != 0
84 && buffer[i + sizeof(uint32_t) + 1] != 0
85 && buffer[i + sizeof(uint32_t) + 2] != 0
86 && buffer[i + sizeof(uint32_t) + 3] != 0)
87 {
88 return i;
89 }
90 if(i > 0xFF) /* Arbitrary guess */
91 return 0;
92 }
93 return 0;
94}
95
96bool crypt_firmware(const char* key, unsigned char* buffer, size_t len)
97{
98 char key_cpy[255];
99 unsigned int i;
100 unsigned int tmp = 0;
101 int key_length = strlen(key);
102
103 strcpy(key_cpy, key);
104 for(i=0; i < strlen(key); i++)
105 key_cpy[i] = key[i] - 1;
106
107 for(i=0; i < len; i++)
108 {
109 buffer[i] ^= key_cpy[tmp] | 0x80;
110 tmp = (tmp + 1) % key_length;
111 }
112
113 return true;
114}
115
116bool inflate_to_buffer(const unsigned char *buffer, size_t len, unsigned char* out_buffer, size_t out_len, char** err_msg)
117{
118 /* Initialize Zlib */
119 z_stream d_stream;
120 int ret;
121
122 d_stream.zalloc = Z_NULL;
123 d_stream.zfree = Z_NULL;
124 d_stream.opaque = Z_NULL;
125
126 d_stream.next_in = (unsigned char*)buffer;
127 d_stream.avail_in = len;
128
129 ret = inflateInit(&d_stream);
130 if (ret != Z_OK)
131 {
132 *err_msg = d_stream.msg;
133 return false;
134 }
135
136 d_stream.next_out = out_buffer;
137 d_stream.avail_out = out_len;
138
139 ret = inflate(&d_stream, Z_SYNC_FLUSH);
140 if(ret < 0)
141 {
142 *err_msg = d_stream.msg;
143 return false;
144 }
145 else
146 inflateEnd(&d_stream);
147
148 return true;
149}
150
151#define CODE_MASK 0xC0
152#define ARGS_MASK 0x3F
153
154#define REPEAT_CODE 0x00
155#define BLOCK_CODE 0x40
156#define LONG_RUN_CODE 0x80
157#define SHORT_RUN_CODE 0xC0
158
159#define BLOCK_ARGS 0x1F
160#define BLOCK_MODE 0x20
161
162
163static void decode_run(unsigned char* dst, uint16_t len, unsigned char val,
164 int* dstidx)
165{
166 memset(dst + *dstidx, val, len);
167 *dstidx += len;
168}
169
170static void decode_pattern(unsigned char* src, unsigned char* dst,
171 uint16_t len, int* srcidx, int* dstidx,
172 bool bdecode, int npasses)
173{
174 int i, j;
175 for (i = 0; i < npasses; i++)
176 {
177 if (bdecode)
178 {
179 for (j = 0; j < len; j++)
180 {
181 uint16_t c, d;
182 c = src[*srcidx + j];
183 d = (c >> 5) & 7;
184 c = (c << 3) & 0xF8;
185 src[*srcidx + j] = (unsigned char)(c | d);
186 }
187 bdecode = false;
188 }
189 memcpy(dst + *dstidx, src + *srcidx, len);
190 *dstidx += len;
191 }
192 *srcidx += len;
193}
194
195int cenc_decode(unsigned char* src, int srclen, unsigned char* dst, int dstlen)
196{
197 int i = 0, j = 0;
198 do
199 {
200 uint16_t c, d, e;
201 c = src[i++];
202 switch (c & CODE_MASK)
203 {
204 case REPEAT_CODE: /* 2 unsigned chars */
205 d = src[i++];
206 d = d + 2;
207
208 e = (c & ARGS_MASK) + 2;
209
210 decode_pattern(src, dst, e, &i, &j, false, d);
211 break;
212
213 case BLOCK_CODE: /* 1/2/3 unsigned chars */
214 d = c & BLOCK_ARGS;
215 if (!(c & BLOCK_MODE))
216 {
217 e = src[i++];
218 e = (d << 8) + (e + 0x21);
219
220 d = (uint16_t)(i ^ j);
221 }
222 else
223 {
224 e = d + 1;
225
226 d = (uint16_t)(i ^ j);
227 }
228 if (d & 1)
229 {
230 i++;
231 }
232
233 decode_pattern(src, dst, e, &i, &j, true, 1);
234 break;
235
236 case LONG_RUN_CODE: /* 3 unsigned chars */
237 d = src[i++];
238 e = ((c & ARGS_MASK) << 8) + (d + 0x42);
239
240 d = src[i++];
241 d = ((d & 7) << 5) | ((d >> 3) & 0x1F);
242
243 decode_run(dst, e, (unsigned char)(d), &j);
244 break;
245
246 case SHORT_RUN_CODE: /* 2 unsigned chars */
247 d = src[i++];
248 d = ((d & 3) << 6) | ((d >> 2) & 0x3F);
249
250 e = (c & ARGS_MASK) + 2;
251
252 decode_run(dst, e, (unsigned char)(d), &j);
253 break;
254 };
255 } while (i < srclen && j < dstlen);
256
257 return j;
258}
259
260/*
261 * Copyright (c) 1999, 2000, 2002 Virtual Unlimited B.V.
262 *
263 * This library is free software; you can redistribute it and/or
264 * modify it under the terms of the GNU Lesser General Public
265 * License as published by the Free Software Foundation; either
266 * version 2.1 of the License, or (at your option) any later version.
267 *
268 * This library is distributed in the hope that it will be useful,
269 * but WITHOUT ANY WARRANTY; without even the implied warranty of
270 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
271 * Lesser General Public License for more details.
272 *
273 * You should have received a copy of the GNU Lesser General Public
274 * License along with this library; if not, write to the Free Software
275 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
276 *
277 */
278
279#define BLOWFISHROUNDS 16
280#define BLOWFISHPSIZE (BLOWFISHROUNDS+2)
281#define WORDS_BIGENDIAN 0
282
283struct blowfishParam
284{
285 uint32_t p[BLOWFISHPSIZE];
286 uint32_t s[1024];
287 uint32_t fdback[2];
288};
289
290typedef enum
291{
292 NOCRYPT,
293 ENCRYPT,
294 DECRYPT
295} cipherOperation;
296
297static inline uint32_t swapu32(uint32_t n)
298{
299 return ( ((n & 0xffU) << 24) |
300 ((n & 0xff00U) << 8) |
301 ((n & 0xff0000U) >> 8) |
302 ((n & 0xff000000U) >> 24) );
303}
304
305static uint32_t _bf_p[BLOWFISHPSIZE] = {
306 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
307 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
308 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
309 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
310 0x9216d5d9, 0x8979fb1b
311};
312
313static uint32_t _bf_s[1024] = {
314 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
315 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
316 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
317 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
318 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
319 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
320 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
321 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
322 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
323 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
324 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
325 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
326 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
327 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
328 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
329 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
330 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
331 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
332 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
333 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
334 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
335 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
336 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
337 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
338 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
339 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
340 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
341 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
342 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
343 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
344 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
345 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
346 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
347 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
348 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
349 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
350 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
351 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
352 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
353 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
354 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
355 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
356 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
357 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
358 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
359 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
360 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
361 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
362 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
363 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
364 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
365 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
366 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
367 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
368 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
369 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
370 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
371 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
372 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
373 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
374 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
375 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
376 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
377 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
378 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
379 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
380 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
381 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
382 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
383 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
384 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
385 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
386 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
387 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
388 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
389 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
390 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
391 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
392 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
393 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
394 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
395 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
396 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
397 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
398 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
399 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
400 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
401 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
402 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
403 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
404 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
405 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
406 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
407 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
408 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
409 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
410 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
411 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
412 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
413 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
414 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
415 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
416 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
417 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
418 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
419 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
420 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
421 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
422 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
423 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
424 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
425 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
426 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
427 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
428 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
429 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
430 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
431 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
432 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
433 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
434 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
435 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
436 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
437 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
438 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
439 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
440 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
441 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
442 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
443 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
444 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
445 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
446 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
447 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
448 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
449 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
450 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
451 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
452 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
453 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
454 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
455 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
456 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
457 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
458 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
459 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
460 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
461 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
462 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
463 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
464 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
465 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
466 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
467 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
468 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
469 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
470 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
471 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
472 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
473 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
474 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
475 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
476 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
477 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
478 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
479 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
480 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
481 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
482 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
483 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
484 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
485 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
486 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
487 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
488 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
489 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
490 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
491 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
492 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
493 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
494 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
495 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
496 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
497 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
498 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
499 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
500 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
501 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
502 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
503 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
504 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
505 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
506 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
507 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
508 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
509 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
510 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
511 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
512 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
513 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
514 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
515 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
516 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
517 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
518 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
519 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
520 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
521 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
522 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
523 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
524 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
525 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
526 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
527 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
528 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
529 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
530 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
531 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
532 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
533 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
534 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
535 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
536 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
537 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
538 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
539 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
540 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
541 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
542 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
543 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
544 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
545 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
546 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
547 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
548 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
549 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
550 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
551 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
552 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
553 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
554 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
555 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
556 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
557 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
558 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
559 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
560 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
561 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
562 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
563 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
564 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
565 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
566 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
567 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
568 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
569 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
570};
571
572#define EROUND(l,r) l ^= *(p++); r ^= ((s[((l>>24)&0xff)+0x000]+s[((l>>16)&0xff)+0x100])^s[((l>>8)&0xff)+0x200])+s[((l>>0)&0xff)+0x300]
573#define DROUND(l,r) l ^= *(p--); r ^= ((s[((l>>24)&0xff)+0x000]+s[((l>>16)&0xff)+0x100])^s[((l>>8)&0xff)+0x200])+s[((l>>0)&0xff)+0x300]
574
575static int blowfishEncrypt(struct blowfishParam* bp, uint32_t* dst, const uint32_t* src)
576{
577 #if WORDS_BIGENDIAN
578 register uint32_t xl = src[0], xr = src[1];
579 #else
580 register uint32_t xl = swapu32(src[0]), xr = swapu32(src[1]);
581 #endif
582 register uint32_t* p = bp->p;
583 register uint32_t* s = bp->s;
584
585 EROUND(xl, xr); EROUND(xr, xl);
586 EROUND(xl, xr); EROUND(xr, xl);
587 EROUND(xl, xr); EROUND(xr, xl);
588 EROUND(xl, xr); EROUND(xr, xl);
589 EROUND(xl, xr); EROUND(xr, xl);
590 EROUND(xl, xr); EROUND(xr, xl);
591 EROUND(xl, xr); EROUND(xr, xl);
592 EROUND(xl, xr); EROUND(xr, xl);
593
594 #if WORDS_BIGENDIAN
595 dst[1] = xl ^ *(p++);
596 dst[0] = xr ^ *(p++);
597 #else
598 dst[1] = swapu32(xl ^ *(p++));
599 dst[0] = swapu32(xr ^ *(p++));
600 #endif
601
602 return 0;
603}
604
605static int blowfishDecrypt(struct blowfishParam* bp, uint32_t* dst, const uint32_t* src)
606{
607 #if WORDS_BIGENDIAN
608 register uint32_t xl = src[0], xr = src[1];
609 #else
610 register uint32_t xl = swapu32(src[0]), xr = swapu32(src[1]);
611 #endif
612 register uint32_t* p = bp->p+BLOWFISHPSIZE-1;
613 register uint32_t* s = bp->s;
614
615 DROUND(xl, xr); DROUND(xr, xl);
616 DROUND(xl, xr); DROUND(xr, xl);
617 DROUND(xl, xr); DROUND(xr, xl);
618 DROUND(xl, xr); DROUND(xr, xl);
619 DROUND(xl, xr); DROUND(xr, xl);
620 DROUND(xl, xr); DROUND(xr, xl);
621 DROUND(xl, xr); DROUND(xr, xl);
622 DROUND(xl, xr); DROUND(xr, xl);
623
624 #if WORDS_BIGENDIAN
625 dst[1] = xl ^ *(p--);
626 dst[0] = xr ^ *(p--);
627 #else
628 dst[1] = swapu32(xl ^ *(p--));
629 dst[0] = swapu32(xr ^ *(p--));
630 #endif
631
632 return 0;
633}
634
635static int blowfishSetup(struct blowfishParam* bp, const unsigned char* key, size_t keybits, cipherOperation op)
636{
637 if ((op != ENCRYPT) && (op != DECRYPT))
638 return -1;
639
640 if (((keybits & 7) == 0) && (keybits >= 32) && (keybits <= 448))
641 {
642 register uint32_t* p = bp->p;
643 register uint32_t* s = bp->s;
644 register unsigned int i, j, k;
645
646 uint32_t tmp, work[2];
647
648 memcpy(s, _bf_s, 1024 * sizeof(uint32_t));
649
650 for (i = 0, k = 0; i < BLOWFISHPSIZE; i++)
651 {
652 tmp = 0;
653 for (j = 0; j < 4; j++)
654 {
655 tmp <<= 8;
656 tmp |= key[k++];
657 if (k >= (keybits >> 3))
658 k = 0;
659 }
660 p[i] = _bf_p[i] ^ tmp;
661 }
662
663 work[0] = work[1] = 0;
664
665 for (i = 0; i < BLOWFISHPSIZE; i += 2, p += 2)
666 {
667 blowfishEncrypt(bp, work, work);
668 #if WORDS_BIGENDIAN
669 p[0] = work[0];
670 p[1] = work[1];
671 #else
672 p[0] = swapu32(work[0]);
673 p[1] = swapu32(work[1]);
674 #endif
675 }
676
677 for (i = 0; i < 1024; i += 2, s += 2)
678 {
679 blowfishEncrypt(bp, work, work);
680 #if WORDS_BIGENDIAN
681 s[0] = work[0];
682 s[1] = work[1];
683 #else
684 s[0] = swapu32(work[0]);
685 s[1] = swapu32(work[1]);
686 #endif
687 }
688
689 /* clear fdback/iv */
690 bp->fdback[0] = 0;
691 bp->fdback[1] = 0;
692
693 return 0;
694 }
695 return -1;
696}
697
698static int blowfishSetIV(struct blowfishParam* bp, const unsigned char* iv)
699{
700 if (iv)
701 memcpy(bp->fdback, iv, 8);
702 else
703 memset(bp->fdback, 0, 8);
704
705 return 0;
706}
707
708#define BLOWFISH_BLOCKSIZE 8
709static int blowfishDecryptCBC(struct blowfishParam* bp, uint32_t* dst, const uint32_t* src, unsigned int nblocks)
710{
711 register const unsigned int blockwords = BLOWFISH_BLOCKSIZE >> 2;
712 register uint32_t* fdback = bp->fdback;
713 register uint32_t* buf = (uint32_t*) malloc(blockwords * sizeof(uint32_t));
714
715 if (buf)
716 {
717 while (nblocks > 0)
718 {
719 register uint32_t tmp;
720 register unsigned int i;
721
722 blowfishDecrypt(bp, buf, src);
723
724 for (i = 0; i < blockwords; i++)
725 {
726 tmp = src[i];
727 dst[i] = buf[i] ^ fdback[i];
728 fdback[i] = tmp;
729 }
730
731 dst += blockwords;
732 src += blockwords;
733
734 nblocks--;
735 }
736 free(buf);
737 return 0;
738 }
739
740 return -1;
741}
742
743bool bf_cbc_decrypt(const unsigned char* key, size_t keylen,
744 unsigned char* data, size_t datalen,
745 const unsigned char* iv)
746{
747 struct blowfishParam param;
748 unsigned char *cipher;
749 unsigned int nblocks;
750
751 if (datalen % BLOWFISH_BLOCKSIZE)
752 return false;
753
754 if (blowfishSetup(&param, key, keylen * 8, ENCRYPT))
755 return false;
756 if (blowfishSetIV(&param, iv))
757 return false;
758
759 cipher = malloc(datalen);
760 memcpy(cipher, data, datalen);
761
762 nblocks = datalen / BLOWFISH_BLOCKSIZE;
763 if (blowfishDecryptCBC(&param, (uint32_t*)data, (uint32_t*)cipher,
764 nblocks))
765 {
766 free(cipher);
767 return false;
768 }
769
770 free(cipher);
771 return true;
772}
773
774uint32_t swap(uint32_t val)
775{
776 return ((val & 0xFF) << 24)
777 | ((val & 0xFF00) << 8)
778 | ((val & 0xFF0000) >> 8)
779 | ((val & 0xFF000000) >> 24);
780}
781
782/* read a file to a buffer */
783enum zen_error_t read_file(const char *file, void **buffer, size_t *size)
784{
785 FILE *f = fopen(file, "rb");
786 if(f == NULL)
787 {
788 printf("[ERR] Cannot open file '%s' for reading: %m\n", file);
789 return ZEN_OPEN_ERROR;
790 }
791 fseek(f, 0, SEEK_END);
792 *size = ftell(f);
793 fseek(f, 0, SEEK_SET);
794 *buffer = malloc(*size);
795 if(fread(*buffer, *size, 1, f) != 1)
796 {
797 free(*buffer);
798 fclose(f);
799 printf("[ERR] Cannot read file '%s': %m\n", file);
800 return ZEN_READ_ERROR;
801 }
802 fclose(f);
803 return ZEN_SUCCESS;
804}
805
806/* write a file from a buffer */
807enum zen_error_t write_file(const char *file, void *buffer, size_t size)
808{
809 FILE *f = fopen(file, "wb");
810 if(f == NULL)
811 {
812 printf("[ERR] Cannot open file '%s' for writing: %m\n", file);
813 return ZEN_OPEN_ERROR;
814 }
815 if(fwrite(buffer, size, 1, f) != 1)
816 {
817 fclose(f);
818 printf("[ERR] Cannot write file '%s': %m\n", file);
819 return ZEN_WRITE_ERROR;
820 }
821 fclose(f);
822 return ZEN_SUCCESS;
823}
824
825/* compute MD5 sum of a buffer */
826enum zen_error_t compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md5sum[16])
827{
828 md5_context ctx;
829 md5_starts(&ctx);
830 md5_update(&ctx, buf, sz);
831 md5_finish(&ctx, file_md5sum);
832 return ZEN_SUCCESS;
833}
834
835/* compute MD5 of a file */
836enum zen_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16])
837{
838 void *buf;
839 size_t sz;
840 enum zen_error_t err = read_file(file, &buf, &sz);
841 if(err != ZEN_SUCCESS)
842 return err;
843 compute_md5sum_buf(buf, sz, file_md5sum);
844 free(buf);
845 return ZEN_SUCCESS;
846}
847
848enum zen_error_t find_pe_data(void *fw, size_t fw_size, uint32_t *data_ptr, uint32_t *data_size)
849{
850 uint8_t *buffer = fw;
851 /* Rudimentary Win32 PE reading to find .data section */
852 if(memcmp(&buffer[0], "MZ", 2) != 0 && memcmp(&buffer[0x118], "PE", 2) != 0)
853 {
854 printf("[ERR] Input file isn't an executable\n");
855 return ZEN_FW_INVALID;
856 }
857 *data_ptr = 0, *data_size = 0;
858 uint32_t start_sec_addr = /*sizeof NT headers */ 0xf8 +
859 /* address of opt header */*(uint32_t *)&buffer[0x3c];
860 for(uint32_t i = start_sec_addr; i < 0x1000; i += 0x28)
861 {
862 if(strcmp((char*)&buffer[i], ".data") == 0)
863 {
864 *data_ptr = le2int(&buffer[i + 0x14]);
865 *data_size = le2int(&buffer[i + 0x10]);
866 break;
867 }
868 }
869 if(*data_ptr == 0 || *data_size == 0)
870 {
871 printf("[ERR] Couldn't find .data section\n");
872 return ZEN_FW_INVALID;
873 }
874 return ZEN_SUCCESS;
875}
876
877int convxdigit(char digit, uint8_t *val)
878{
879 if(digit >= '0' && digit <= '9')
880 {
881 *val = digit - '0';
882 return 0;
883 }
884 else if(digit >= 'A' && digit <= 'F')
885 {
886 *val = digit - 'A' + 10;
887 return 0;
888 }
889 else if(digit >= 'a' && digit <= 'f')
890 {
891 *val = digit - 'a' + 10;
892 return 0;
893 }
894 else
895 return 1;
896}
diff --git a/rbutil/mkzenboot/utils.h b/rbutil/mkzenboot/utils.h
new file mode 100644
index 0000000000..56edb4e20b
--- /dev/null
+++ b/rbutil/mkzenboot/utils.h
@@ -0,0 +1,53 @@
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#ifndef __UTILS__
22#define __UTILS__
23
24#include <stddef.h>
25#include <stdint.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <stdbool.h>
29#include <string.h>
30#include "mkzenboot.h"
31#include "hmac-sha1.h"
32
33int filesize(FILE* fd);
34unsigned int le2int(unsigned char* buf);
35unsigned int be2int(unsigned char* buf);
36void int2le(unsigned int val, unsigned char* addr);
37const char* find_firmware_key(const unsigned char* buffer, size_t len);
38uint32_t find_firmware_offset(unsigned char* buffer, size_t len);
39bool crypt_firmware(const char* key, unsigned char* buffer, size_t len);
40bool inflate_to_buffer(const unsigned char *buffer, size_t len,
41 unsigned char* out_buffer, size_t out_len, char** err_msg);
42int cenc_decode(unsigned char* src, int srclen, unsigned char* dst, int dstlen);
43bool bf_cbc_decrypt(const unsigned char* key, size_t keylen, unsigned char* data,
44 size_t datalen, const unsigned char* iv);
45uint32_t swap(uint32_t val);
46enum zen_error_t compute_md5sum(const char *file, uint8_t file_md5sum[16]);
47enum zen_error_t compute_md5sum_buf(void *buf, size_t sz, uint8_t file_md5sum[16]);
48enum zen_error_t read_file(const char *file, void **buffer, size_t *size);
49enum zen_error_t write_file(const char *file, void *buffer, size_t size);
50enum zen_error_t find_pe_data(void *fw, size_t fw_size, uint32_t *data_ptr, uint32_t *data_size);
51int convxdigit(char digit, uint8_t *val);
52
53#endif /* __UTILS__ */ \ No newline at end of file