summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-10-03 14:27:19 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2012-10-03 14:27:19 +0200
commit821efc46ec9392a58df95b396fd51972cf5fd3e7 (patch)
treeb6810a45d5f5405ec9a24e82bb09a09485cfff37
parent8687b9899382b6008c66a89dbc01271437f7654d (diff)
downloadrockbox-821efc46ec9392a58df95b396fd51972cf5fd3e7.tar.gz
rockbox-821efc46ec9392a58df95b396fd51972cf5fd3e7.zip
Introduce atjboottool for ATJ213x firmwares
Change-Id: Ie857b82e25de235c8549defab7e75995efefb3f6
-rw-r--r--utils/atj2137/atjboottool/Makefile20
-rw-r--r--utils/atj2137/atjboottool/atj_tables.c138
-rw-r--r--utils/atj2137/atjboottool/atj_tables.h16
-rw-r--r--utils/atj2137/atjboottool/atjboottool.c1435
-rw-r--r--utils/atj2137/atjboottool/misc.c53
-rw-r--r--utils/atj2137/atjboottool/misc.h41
6 files changed, 1703 insertions, 0 deletions
diff --git a/utils/atj2137/atjboottool/Makefile b/utils/atj2137/atjboottool/Makefile
new file mode 100644
index 0000000000..14f25475f6
--- /dev/null
+++ b/utils/atj2137/atjboottool/Makefile
@@ -0,0 +1,20 @@
1DEFINES=
2CC=gcc
3LD=gcc
4CFLAGS=-g -std=c99 -W -Wall $(DEFINES)
5LDFLAGS=
6BINS=atjboottool
7
8all: $(BINS)
9
10%.o: %.c
11 $(CC) $(CFLAGS) -c -o $@ $<
12
13atjboottool: atjboottool.o misc.o atj_tables.o
14 $(LD) -o $@ $^ $(LDFLAGS)
15
16clean:
17 rm -fr *.o
18
19veryclean:
20 rm -rf $(BINS)
diff --git a/utils/atj2137/atjboottool/atj_tables.c b/utils/atj2137/atjboottool/atj_tables.c
new file mode 100644
index 0000000000..92ceafc769
--- /dev/null
+++ b/utils/atj2137/atjboottool/atj_tables.c
@@ -0,0 +1,138 @@
1#include <stdint.h>
2
3uint8_t g_check_block_A_table[1024] =
4{
5 0x16, 0x2b, 0x01, 0xe4, 0x0e, 0x3d, 0xc1, 0xdf, 0x0f, 0x35, 0x8f, 0xf5, 0xe2,
6 0x48, 0xa0, 0x2e, 0x1c, 0x6a, 0x57, 0xea, 0x6d, 0x9a, 0xe2, 0x03, 0xec, 0xe8,
7 0x84, 0x9c, 0x87, 0xca, 0xba, 0xcf, 0xdb, 0x5c, 0x6f, 0xf2, 0x32, 0x72, 0xe9,
8 0x50, 0x42, 0x06, 0x1b, 0xe9, 0x9d, 0x8f, 0xa4, 0xff, 0x66, 0x64, 0x59, 0xb7,
9 0xd0, 0x15, 0x3c, 0x42, 0x27, 0x25, 0x52, 0x47, 0x83, 0x09, 0x7c, 0x55, 0x1d,
10 0xc1, 0x12, 0xfa, 0x7c, 0xaa, 0xf8, 0x60, 0xc6, 0x65, 0x3a, 0xf3, 0x13, 0x44,
11 0xa7, 0x5e, 0xc7, 0x22, 0x7e, 0x91, 0xdf, 0x98, 0xf2, 0x8a, 0x08, 0x2c, 0x32,
12 0x77, 0x6a, 0x72, 0xff, 0x3d, 0xa6, 0x13, 0x0c, 0xbe, 0x3e, 0x4b, 0xe9, 0x76,
13 0x35, 0x85, 0x93, 0x91, 0x9b, 0x25, 0x14, 0x10, 0x08, 0x49, 0x39, 0xa9, 0x9a,
14 0x9c, 0x06, 0x1c, 0x4b, 0xf9, 0xae, 0x12, 0x94, 0xfa, 0x08, 0x55, 0xaa, 0x05,
15 0x58, 0x10, 0x29, 0x80, 0x76, 0xe4, 0xac, 0x4b, 0x67, 0xdc, 0xdf, 0x87, 0x19,
16 0x6d, 0x42, 0x66, 0x7c, 0x8c, 0xf7, 0x8d, 0x01, 0x29, 0x35, 0xba, 0xc7, 0x60,
17 0x4d, 0xe1, 0xb7, 0xd3, 0xe7, 0xe3, 0xb0, 0x67, 0x3e, 0x38, 0x40, 0x67, 0x76,
18 0xd8, 0xa7, 0xd3, 0xd4, 0x72, 0xa4, 0x70, 0xb6, 0x31, 0x51, 0xa0, 0x40, 0x4f,
19 0xaf, 0xab, 0x52, 0x8c, 0xf7, 0xf8, 0x74, 0x98, 0xaf, 0xbe, 0x6e, 0x23, 0xd7,
20 0x47, 0xa1, 0x5d, 0x1b, 0x4e, 0xa2, 0x97, 0xd9, 0xc2, 0x26, 0x79, 0xb9, 0xf8,
21 0xae, 0x5e, 0x04, 0x6d, 0xd5, 0xd0, 0xa7, 0x98, 0x6a, 0xce, 0xaa, 0x5f, 0xe4,
22 0xf9, 0xb8, 0xd2, 0xbe, 0x1e, 0xcc, 0x55, 0xcb, 0x70, 0x0f, 0x6f, 0x81, 0x28,
23 0xcb, 0xf8, 0x8c, 0x5d, 0x7e, 0x55, 0xd3, 0x27, 0xc9, 0xa9, 0x85, 0xa6, 0xc0,
24 0xf5, 0x79, 0xed, 0xc0, 0x7b, 0x1c, 0x36, 0xc3, 0xbd, 0xa5, 0x8e, 0xa8, 0x77,
25 0x60, 0xe0, 0x39, 0xcd, 0x9a, 0x65, 0x60, 0x8b, 0x33, 0xfc, 0x2b, 0x49, 0xa8,
26 0xca, 0x67, 0xba, 0x44, 0xaf, 0xf9, 0x29, 0x5d, 0x71, 0x30, 0x85, 0xe0, 0xe5,
27 0x16, 0xe0, 0x25, 0x44, 0xc2, 0xab, 0x42, 0xf3, 0x48, 0x26, 0x01, 0x3f, 0x09,
28 0x59, 0xf5, 0x7f, 0xde, 0xce, 0x49, 0x23, 0x38, 0xc6, 0x55, 0xd1, 0x47, 0xc6,
29 0x5b, 0xee, 0x9b, 0x6a, 0x9d, 0x0d, 0x72, 0x3c, 0x36, 0x39, 0xf9, 0xdd, 0xf1,
30 0xd3, 0x84, 0x70, 0xe9, 0x05, 0x12, 0x10, 0x62, 0xcb, 0x6e, 0xbc, 0x3f, 0xcb,
31 0x34, 0x73, 0xf6, 0x6f, 0xc4, 0x17, 0x0d, 0xe8, 0xeb, 0x25, 0x5c, 0xdf, 0xa0,
32 0x86, 0x8c, 0xc3, 0xb9, 0x4a, 0xbb, 0x7e, 0x38, 0xc1, 0x17, 0x08, 0xd0, 0x93,
33 0x0f, 0x3e, 0xcf, 0x27, 0x71, 0xa0, 0x72, 0xe7, 0xee, 0x7b, 0x41, 0x33, 0x4d,
34 0xfb, 0xaf, 0x5c, 0x55, 0xf7, 0xdc, 0xd9, 0xf2, 0x14, 0x7d, 0xea, 0xe3, 0x08,
35 0xd6, 0xd3, 0xa0, 0xfa, 0x52, 0x17, 0x1b, 0x10, 0xce, 0x70, 0xb6, 0xb9, 0xcf,
36 0xb4, 0x25, 0x9b, 0x42, 0x53, 0x67, 0x2b, 0x57, 0x7c, 0xff, 0x72, 0xa1, 0x83,
37 0xcd, 0x08, 0xd3, 0x11, 0xae, 0x30, 0x9c, 0x0a, 0x01, 0x25, 0x73, 0x45, 0x7a,
38 0xfe, 0x78, 0xe9, 0xf6, 0x3f, 0x5d, 0x0a, 0x35, 0x9f, 0x45, 0x48, 0x04, 0x48,
39 0xfe, 0x81, 0xc2, 0xc4, 0x82, 0x41, 0xde, 0xa2, 0xb1, 0x67, 0x6a, 0x3b, 0x5b,
40 0x0c, 0x06, 0xb4, 0x6e, 0xe6, 0x0e, 0x15, 0xef, 0x12, 0x3c, 0x7c, 0xd7, 0x49,
41 0xf3, 0x9c, 0x5b, 0x06, 0xf1, 0x2b, 0x45, 0xec, 0x99, 0x45, 0xaf, 0x10, 0x17,
42 0x60, 0x66, 0x49, 0x85, 0x75, 0x02, 0x3d, 0xae, 0xe4, 0x15, 0xa8, 0xd7, 0xdf,
43 0xb7, 0x95, 0xa3, 0x2d, 0xb3, 0x55, 0x19, 0x46, 0x3d, 0x62, 0x88, 0x08, 0x66,
44 0xf9, 0x4a, 0xb3, 0xa3, 0x3e, 0x85, 0x79, 0x20, 0xaf, 0xed, 0xa7, 0x41, 0xa2,
45 0x8f, 0xa8, 0x84, 0x93, 0x46, 0x88, 0xb0, 0x1e, 0x88, 0x58, 0x0b, 0x16, 0xc6,
46 0x28, 0x4b, 0x01, 0x7d, 0x8d, 0x54, 0x61, 0x1d, 0x57, 0x94, 0xfb, 0x84, 0x6b,
47 0xea, 0xa4, 0x86, 0x98, 0x1b, 0x5e, 0xdb, 0x53, 0xcd, 0xf6, 0x0b, 0x44, 0xf0,
48 0xa9, 0xb0, 0xcd, 0x1f, 0xda, 0x5e, 0xd0, 0xea, 0xb1, 0xe1, 0x70, 0xdf, 0x16,
49 0x44, 0xc2, 0xd0, 0x97, 0xf9, 0xca, 0x88, 0x93, 0xf6, 0x4c, 0x12, 0xa3, 0x91,
50 0x2f, 0x16, 0x9f, 0x7b, 0xef, 0x2a, 0x7c, 0x47, 0xf1, 0xbf, 0x16, 0xd6, 0x7b,
51 0xfc, 0x49, 0x91, 0xd9, 0xee, 0x84, 0xa8, 0xed, 0x84, 0xfb, 0x2d, 0x84, 0x2d,
52 0x0c, 0x4e, 0xad, 0xee, 0x26, 0x81, 0xb2, 0x61, 0x27, 0x14, 0x3a, 0x9a, 0x32,
53 0x2f, 0xf6, 0xac, 0xa7, 0xc6, 0xaa, 0x57, 0x37, 0x02, 0x23, 0x94, 0x26, 0xd3,
54 0xe5, 0x12, 0x84, 0xdc, 0x53, 0x43, 0x76, 0x91, 0x79, 0xf6, 0x83, 0xef, 0x4a,
55 0x4c, 0xd8, 0x31, 0x76, 0x7d, 0xb4, 0xe3, 0xb2, 0x78, 0x5c, 0x9d, 0xf4, 0xf7,
56 0x71, 0xf9, 0xd7, 0xdb, 0x64, 0xad, 0x8b, 0x36, 0x62, 0x2c, 0xd5, 0x38, 0x32,
57 0x9e, 0x7b, 0xb3, 0xca, 0x83, 0xb3, 0x98, 0x78, 0x46, 0x9b, 0xf6, 0x69, 0xa0,
58 0x57, 0xdb, 0x82, 0x8a, 0x3b, 0xaa, 0x69, 0x01, 0x1a, 0xf4, 0x1d, 0x80, 0x8f,
59 0xa8, 0x19, 0x78, 0xe2, 0x56, 0x79, 0x78, 0x38, 0xb4, 0x09, 0x5c, 0x8d, 0x14,
60 0xf1, 0x35, 0x7a, 0x23, 0xa1, 0xe1, 0x83, 0xaa, 0xf9, 0xbe, 0x5b, 0x81, 0x3a,
61 0xdc, 0x83, 0x47, 0xf9, 0xd1, 0xe4, 0x24, 0x84, 0xfd, 0x51, 0xb8, 0x8a, 0xf5,
62 0xe3, 0x70, 0xee, 0xb4, 0xa6, 0x55, 0x57, 0xb5, 0xe3, 0xb9, 0x2e, 0xfa, 0x26,
63 0x48, 0x01, 0xcd, 0x4a, 0x79, 0x70, 0x61, 0x76, 0xd6, 0xe9, 0xcd, 0x40, 0x63,
64 0x64, 0x1f, 0xdd, 0xe4, 0x6e, 0x39, 0xb3, 0x3e, 0x3d, 0x28, 0xe4, 0xf6, 0x0b,
65 0x6c, 0x7a, 0xa9, 0x0d, 0xcd, 0xd4, 0x5e, 0x33, 0xf7, 0x03, 0xde, 0x74, 0x51,
66 0xd3, 0xe0, 0x69, 0x58, 0x48, 0x5f, 0x80, 0x8f, 0x73, 0x61, 0x16, 0xe7, 0x1c,
67 0x17, 0x34, 0x14, 0x7a, 0x93, 0xba, 0x3a, 0xbc, 0x21, 0x61, 0xa9, 0x54, 0xe7,
68 0x89, 0x76, 0xf7, 0xb5, 0x86, 0x18, 0x76, 0x30, 0x26, 0x43, 0x50, 0xe8, 0x91,
69 0x6b, 0xa8, 0xd9, 0x9a, 0x8f, 0xe1, 0x79, 0x9d, 0x9f, 0x13, 0xf7, 0x16, 0xf7,
70 0xe1, 0xeb, 0xd7, 0xd5, 0x5e, 0xa7, 0x45, 0x4a, 0x7e, 0x6e, 0x3b, 0x62, 0xaa,
71 0x85, 0xa2, 0xfb, 0xa1, 0x2f, 0x47, 0x9d, 0xcf, 0xf0, 0xcc, 0x91, 0xb9, 0x3c,
72 0xb4, 0x79, 0xe5, 0x68, 0x22, 0xaa, 0x1d, 0x2e, 0x5c, 0x86, 0x3b, 0x2a, 0x28,
73 0x3e, 0x88, 0xd1, 0xc2, 0xc9, 0x32, 0x3b, 0x97, 0xa7, 0xd7, 0x48, 0xc4, 0x65,
74 0xdd, 0x1b, 0xa2, 0xba, 0x20, 0xd4, 0x21, 0x38, 0x40, 0x0c, 0x18, 0x40, 0x77,
75 0x2e, 0x55, 0xb5, 0x78, 0x65, 0xc9, 0x2e, 0x2d, 0x5a, 0x43, 0x41, 0xd5, 0x9e,
76 0x71, 0x68, 0x76, 0x07, 0x66, 0xfc, 0x1c, 0x26, 0xdf, 0x18, 0xa7, 0xe4, 0x5a,
77 0x53, 0x9b, 0x50, 0x47, 0x76, 0xc5, 0xe1, 0xff, 0x4b, 0x10, 0x29, 0x1f, 0x5c,
78 0x57, 0x58, 0xc1, 0xc3, 0xb1, 0xf7, 0xdd, 0x24, 0xd1, 0xaf, 0x13, 0xb1, 0x13,
79 0xfb, 0x2a, 0x06, 0xcf, 0xc5, 0x47, 0x58, 0xa0, 0xbd, 0x0c, 0xf2, 0xbb, 0x3d,
80 0xcb, 0x01, 0x91, 0xa3, 0xc9, 0x4e, 0xb6, 0x76, 0x35, 0x22, 0xec, 0x84, 0x7c,
81 0xe1, 0x0b, 0xb9, 0xc4, 0xae, 0x1b, 0xf6, 0x84, 0xbf, 0x76, 0x40, 0x65, 0x6c,
82 0x1f, 0x2a, 0xbe, 0x01, 0x95, 0xbd, 0xaa, 0x09, 0xf2, 0x86, 0x46, 0xb1, 0x52,
83 0x6b, 0x24, 0x47, 0x8f, 0x4b, 0x4d, 0x98, 0x95, 0x56, 0x42
84};
85
86uint8_t g_decode_B_table[20] =
87{
88 0x20, 0xf9, 0xd7, 0x56, 0x30, 0x24, 0x55, 0xa9, 0x7a, 0xd7, 0x25, 0xe5, 0xed,
89 0xf8, 0xb4, 0x36, 0x41, 0xc5, 0x51, 0xaf
90};
91
92uint32_t g_xor_key[9] =
93{
94 1, 0, 0, 0, 0, 0, 0, 0, 0
95};
96
97uint32_t g_crypto_table[8] =
98{
99 0xefad6126, 0x0a4c9d6e, 0x19c26bf5, 0x149563a4, 0x29f22ff4, 0x7e731af1,
100 0x32ba853a, 0x00000172
101};
102
103uint32_t g_crypto_table2[8] =
104{
105 0x56fae6a3, 0x56e0c110, 0xf18aeb9b, 0x27a8cd9b, 0x555a67c4, 0x19b7f70f,
106 0x537dece8, 0x000001db
107};
108
109uint32_t g_crypto_key6[8] =
110{
111 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
112 0x00000000, 0x00000000
113};
114
115uint32_t g_crypto_key3[6] =
116{
117 0xe8343e36, 0xd4994637, 0xa0991168, 0x86a2d57e, 0xf0eba162, 0x00000003
118};
119
120uint32_t g_crypto_key4[6] =
121{
122 0x797324f1, 0xb11c5c0c, 0xa2cdd545, 0x71a0094f, 0xd51fbc6c, 0x00000000
123};
124
125uint32_t g_crypto_data3[6] =
126{
127 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
128};
129
130uint32_t g_crypto_key5[6] =
131{
132 0x4a3205fd, 0x512f7874, 0x1481eb10, 0xb8c953ca, 0x0a601907, 0x00000002
133};
134
135uint32_t g_crypto_data[8] =
136{
137 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
138};
diff --git a/utils/atj2137/atjboottool/atj_tables.h b/utils/atj2137/atjboottool/atj_tables.h
new file mode 100644
index 0000000000..2171453c01
--- /dev/null
+++ b/utils/atj2137/atjboottool/atj_tables.h
@@ -0,0 +1,16 @@
1#ifndef __ATJ_TABLES__
2#define __ATJ_TABLES__
3
4uint8_t g_check_block_A_table[1024];
5uint8_t g_decode_B_table[20];
6uint32_t g_xor_key[9];
7uint32_t g_crypto_table[8];
8uint32_t g_crypto_table2[8];
9uint32_t g_crypto_key6[8];
10uint32_t g_crypto_key3[6];
11uint32_t g_crypto_key4[6];
12uint32_t g_crypto_key5[6];
13uint32_t g_crypto_data[8];
14uint32_t g_crypto_data3[6];
15
16#endif // __ATJ_TABLES__
diff --git a/utils/atj2137/atjboottool/atjboottool.c b/utils/atj2137/atjboottool/atjboottool.c
new file mode 100644
index 0000000000..3fb9874712
--- /dev/null
+++ b/utils/atj2137/atjboottool/atjboottool.c
@@ -0,0 +1,1435 @@
1#include <stdio.h>
2#include <stdint.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <string.h>
6#include <getopt.h>
7#include <stdarg.h>
8#include <ctype.h>
9#include "misc.h"
10#include "elf.h"
11
12#ifndef MIN
13#define MIN(a,b) ((a) < (b) ? (a) : (b))
14#endif
15
16#define cprintf(col, ...) do {color(col); printf(__VA_ARGS__); }while(0)
17
18#define cprintf_field(str1, ...) do{ cprintf(GREEN, str1); cprintf(YELLOW, __VA_ARGS__); }while(0)
19
20bool g_debug = false;
21char *g_out_prefix = NULL;
22bool g_force = false;
23
24#define let_the_force_flow(x) do { if(!g_force) return x; } while(0)
25#define continue_the_force(x) if(x) let_the_force_flow(x)
26
27#define check_field(v_exp, v_have, str_ok, str_bad) \
28 if((v_exp) != (v_have)) \
29 { cprintf(RED, str_bad); let_the_force_flow(__LINE__); } \
30 else { cprintf(RED, str_ok); }
31
32static void print_hex(void *p, int size, int unit)
33{
34 uint8_t *p8 = p;
35 uint16_t *p16 = p;
36 uint32_t *p32 = p;
37 for(int i = 0; i < size; i += unit, p8++, p16++, p32++)
38 {
39 if(i != 0 && (i % 16) == 0)
40 printf("\n");
41 if(unit == 1)
42 printf(" %02x", *p8);
43 else if(unit == 2)
44 printf(" %04x", *p16);
45 else
46 printf(" %08x", *p32);
47 }
48}
49
50/**
51 * FWU
52 **/
53
54#define FWU_SIG_SIZE 16
55#define FWU_BLOCK_SIZE 512
56
57struct fwu_hdr_t
58{
59 uint8_t sig[FWU_SIG_SIZE];
60 uint32_t fw_size;
61 uint32_t block_size;// always 512
62 uint8_t version;
63 uint8_t unk;
64 uint8_t sig2[FWU_SIG_SIZE];
65} __attribute__((packed));
66
67const uint8_t g_fwu_signature[FWU_SIG_SIZE] =
68{
69 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x75
70};
71
72struct version_desc_t
73{
74 uint8_t version;
75 uint8_t value;
76 uint8_t unk;
77 uint8_t sig2[FWU_SIG_SIZE];
78};
79
80struct version_desc_t g_version[] =
81{
82 { 1, 0xd, 0xd0, { 0x76, 0x5c, 0x50, 0x94, 0x69, 0xb0, 0xa7, 0x03, 0x10, 0xf1, 0x7e, 0xdb, 0x88, 0x90, 0x86, 0x9d } },
83 { 1, 0xe, 0xd0, { 0x92, 0x22, 0x7a, 0x77, 0x08, 0x67, 0xae, 0x06, 0x16, 0x06, 0xb8, 0x65, 0xa6, 0x42, 0xf7, 0X52 } },
84 { 3, 0x7e, 0xe1, { 0x3f, 0xad, 0xf8, 0xb0, 0x2e, 0xaf, 0x67, 0x49, 0xb9, 0x85, 0x5f, 0x63, 0x4e, 0x5e, 0x8e, 0x2e } },
85};
86
87#define NR_VERSIONS (int)(sizeof(g_version)/sizeof(g_version[0]))
88
89typedef struct ptr_bundle_t
90{
91 uint32_t *ptrA;
92 uint32_t *ptrB;
93}ptr_bundle_t;
94
95struct block_A_info_t
96{
97 int nr_bits;
98 uint16_t field_2;
99 int nr_words;
100 int nr_dwords_x12;
101 uint32_t *ptr6; // size
102 uint32_t *ptr7; // size
103 uint32_t *ptr5; // size
104 uint32_t size;
105 uint32_t field_1C;
106 ptr_bundle_t ptr1;
107 uint32_t *ptr3; // size
108 uint32_t *ptr4; // size
109 int nr_words2;
110 uint32_t field_34;
111 int nr_dwords_x8;
112 int nr_bytes;
113 int nr_bytes2;
114 int nr_dwords_m1;
115 int nr_dwords_x2_m1;
116 int nr_dwords_x2;
117 int nr_dwords;
118 uint32_t field_54;
119 uint32_t field_58;
120};
121
122struct block_A_info_t g_decode_A_info;
123uint8_t g_subblock_A[0x128];
124uint8_t g_key_B[20];
125uint8_t g_perm_B[258];
126uint8_t g_crypto_info_byte;
127uint8_t *g_decode_buffer;
128uint8_t *g_decode_buffer2;
129void *g_decode_buffer3;
130
131#include "atj_tables.h"
132
133void compute_checksum(uint8_t *buf, int size, uint8_t t[20])
134{
135 memset(t, 0, 20);
136
137 for(int i = 0; i < size; i++)
138 t[i % 20] ^= buf[i];
139 for(int i = 0; i < 20; i++)
140 t[i] = ~t[i];
141}
142
143int check_block(uint8_t *buf, uint8_t ref[20], unsigned size)
144{
145 uint8_t t[20];
146 compute_checksum(buf, size, t);
147
148 return memcmp(ref, t, 20);
149}
150
151
152int get_version(uint8_t *buf, unsigned long size)
153{
154 (void) size;
155 struct fwu_hdr_t *hdr = (void *)buf;
156 for(int i = 0; i < NR_VERSIONS; i++)
157 if(hdr->version == g_version[i].value)
158 return i;
159 return -1;
160}
161
162static int decode_block_A(uint8_t block[1020])
163{
164 uint8_t *p = &g_check_block_A_table[32 * (block[998] & 0x1f)];
165 uint8_t key[32];
166
167 for(int i = 0; i < 20; i++)
168 {
169 block[1000 + i] ^= p[i];
170 key[i] = block[1000 + i];
171 }
172 for(int i = 20; i < 32; i++)
173 key[i] = key[i - 20];
174
175 for(int i = 0; i < 992; i++)
176 block[i] ^= key[i % 32] ^ g_check_block_A_table[i];
177
178 return check_block(block - 1, block + 1000, 1001);
179}
180
181static void compute_perm(uint8_t *keybuf, int size, uint8_t perm[258])
182{
183 for(int i = 0; i < 256; i++)
184 perm[i] = i;
185 perm[256] = perm[257] = 0;
186 uint8_t idx = 0;
187 for(int i = 0; i < 256; i++)
188 {
189 uint8_t v = perm[i];
190 idx = (v + keybuf[i % size] + idx) % 256;
191 perm[i] = perm[idx];
192 perm[idx] = v;
193 }
194}
195
196static void decode_perm(uint8_t *buf, int size, uint8_t perm[258])
197{
198 uint8_t idxa = perm[256];
199 uint8_t idxb = perm[257];
200 for(int i = 0; i < size; i++)
201 {
202 idxa = (idxa + 1) % 256;
203 uint8_t v = perm[idxa];
204 idxb = (idxb + v) % 256;
205 perm[idxa] = perm[idxb];
206 perm[idxb] = v;
207 buf[i] ^= perm[(v + perm[idxa]) % 256];
208 }
209}
210
211static void decode_block_with_perm(uint8_t *keybuf, int keysize,
212 uint8_t *buf, int bufsize, uint8_t perm[258])
213{
214 compute_perm(keybuf, keysize, perm);
215 decode_perm(buf, bufsize, perm);
216}
217
218static void apply_perm(uint8_t *inbuf, uint8_t *outbuf, int size, int swap)
219{
220 memcpy(outbuf, inbuf, size);
221 int a = swap & 0xf;
222 int b = (swap >> 4) + 16;
223 uint8_t v = outbuf[a];
224 outbuf[a] = outbuf[b];
225 outbuf[b] = v;
226}
227
228static void decode_block_with_swap(uint8_t keybuf[32], int swap,
229 uint8_t *buf, int bufsize, uint8_t perm[258])
230{
231 uint8_t keybuf_interm[32];
232
233 apply_perm(keybuf, keybuf_interm, 32, swap);
234 decode_block_with_perm(keybuf_interm, 32, buf, bufsize, perm);
235}
236
237static void clear_memory(void *buf, int size_dwords)
238{
239 memset(buf, 0, 4 * size_dwords);
240}
241
242static void set_bit(int bit_pos, uint32_t *buf)
243{
244 buf[bit_pos / 32] |= 1 << (bit_pos % 32);
245}
246
247static int fill_decode_info(uint8_t sz)
248{
249 if(sz == 2) sz = 233;
250 else if(sz == 3) sz = 163;
251 else return 1;
252
253 g_decode_A_info.nr_bits = sz;
254 g_decode_A_info.nr_bytes2 = sz / 8 + (sz % 8 != 0);
255 g_decode_A_info.nr_words = 2 * g_decode_A_info.nr_bytes2;
256 g_decode_A_info.nr_bytes = sz / 8 + (sz % 8 != 0);
257 g_decode_A_info.nr_words2 = 2 * g_decode_A_info.nr_bytes2;
258 g_decode_A_info.nr_dwords = sz / 32 + (sz % 32 != 0);
259 g_decode_A_info.size = 4 * g_decode_A_info.nr_dwords;
260 g_decode_A_info.nr_dwords_x8 = 8 * g_decode_A_info.nr_dwords;
261 g_decode_A_info.nr_dwords_m1 = g_decode_A_info.nr_dwords - 1;
262 g_decode_A_info.nr_dwords_x2 = 2 * g_decode_A_info.nr_dwords;
263 g_decode_A_info.nr_dwords_x2_m1 = g_decode_A_info.nr_dwords_x2 - 1;
264 g_decode_A_info.nr_dwords_x12 = 12 * g_decode_A_info.nr_dwords;
265 g_decode_A_info.ptr1.ptrA = malloc(4 * g_decode_A_info.nr_dwords);
266 g_decode_A_info.ptr1.ptrB = malloc(g_decode_A_info.size);
267 g_decode_A_info.ptr3 = malloc(g_decode_A_info.size);
268 g_decode_A_info.ptr4 = malloc(g_decode_A_info.size);
269 g_decode_A_info.ptr5 = malloc(g_decode_A_info.size);
270 g_decode_A_info.ptr6 = malloc(g_decode_A_info.size);
271 g_decode_A_info.ptr7 = malloc(g_decode_A_info.size);
272
273 cprintf(BLUE, " Decode Info:\n");
274 cprintf_field(" Nr Bits: ", "%d\n", g_decode_A_info.nr_bits);
275 cprintf_field(" Nr Bytes: ", "%d\n", g_decode_A_info.nr_bytes);
276 cprintf_field(" Nr Bytes 2: ", "%d\n", g_decode_A_info.nr_bytes2);
277 cprintf_field(" Nr Words: ", "%d\n", g_decode_A_info.nr_words);
278 cprintf_field(" Nr Words 2: ", "%d\n", g_decode_A_info.nr_words2);
279 cprintf_field(" Nr DWords: ", "%d\n", g_decode_A_info.nr_dwords);
280 cprintf_field(" Size: ", "%d\n", g_decode_A_info.size);
281
282 return 0;
283}
284
285static int process_block_A(uint8_t block[1024])
286{
287 cprintf(BLUE, "Block A\n");
288 int ret = decode_block_A(block + 4);
289 cprintf(GREEN, " Check: ");
290 check_field(ret, 0, "Pass\n", "Fail\n");
291
292 memcpy(g_subblock_A, block, sizeof(g_subblock_A));
293 ret = fill_decode_info(g_subblock_A[276]);
294 cprintf(GREEN, " Info: ");
295 check_field(ret, 0, "Pass\n", "Fail\n");
296
297 int tmp = 2 * g_decode_A_info.nr_bytes2 + 38;
298 int offset = 1004 - tmp + 5;
299 g_crypto_info_byte = block[offset - 1];
300 g_decode_buffer = malloc(g_decode_A_info.size);
301 g_decode_buffer2 = malloc(g_decode_A_info.size);
302
303 memset(g_decode_buffer, 0, g_decode_A_info.size);
304 memset(g_decode_buffer2, 0, g_decode_A_info.size);
305
306 memcpy(g_decode_buffer, &block[offset], g_decode_A_info.nr_bytes2);
307 int offset2 = g_decode_A_info.nr_bytes2 + offset;
308 memcpy(g_decode_buffer2, &block[offset2], g_decode_A_info.nr_bytes2);
309
310
311 cprintf_field(" Word: ", "%d ", *(uint16_t *)&g_subblock_A[286]);
312 check_field(*(uint16_t *)&g_subblock_A[286], 1, "Ok\n", "Mismatch\n");
313
314 return 0;
315}
316
317static void decode_key_B(uint8_t buf[20], uint8_t buf2[16], uint8_t key[20])
318{
319 for(int i = 0; i < 20; i++)
320 {
321 uint8_t v = buf[i] ^ g_decode_B_table[i];
322 key[i] = v;
323 buf[i] = v ^ buf2[i % 16];
324 }
325}
326
327static void decode_block_B(uint8_t *buf, uint8_t key[16], int size)
328{
329 decode_key_B(&buf[size], key, g_key_B);
330 decode_block_with_perm(g_key_B, 20, buf, size, g_perm_B);
331}
332
333static int find_last_bit_set(uint32_t *buf, bool a)
334{
335 int i = a ? g_decode_A_info.nr_dwords_m1 : g_decode_A_info.nr_dwords_x2_m1;
336
337 while(i >= 0 && buf[i] == 0)
338 i--;
339 if(i < 0)
340 return -1;
341 for(int j = 31; j >= 0; j--)
342 if(buf[i] & (1 << j))
343 return 32 * i + j;
344 return -1; // unreachable
345}
346
347static void xor_with_ptrs(uint8_t *buf, ptr_bundle_t *ptrs)
348{
349 /*
350 int sz = g_decode_A_info.nr_bytes2 - 1;
351 if(sz <= 32)
352 {
353 for(int i = 0; i < sz; i++)
354 buf[i] ^= ptrs->ptrA[i];
355 for(int i = sz; i < 32; i++)
356 buf[i] ^= ptrs->ptrB[i - sz];
357 }
358 else
359 for(int i = 0; i < 32; i++)
360 buf[i] ^= ptrs->ptrA[i];
361 */
362 uint8_t *ptrA = (uint8_t *)ptrs->ptrA;
363 uint8_t *ptrB = (uint8_t *)ptrs->ptrB;
364 int sz = MIN(g_decode_A_info.nr_bytes2 - 1, 32);
365 for(int i = 0; i < sz; i++)
366 buf[i] ^= ptrA[i];
367 for(int i = sz; i < 32; i++)
368 buf[i] ^= ptrB[i - sz];
369}
370
371static void copy_memory(uint32_t *to, uint32_t *from)
372{
373 for(int i = 0; i < g_decode_A_info.nr_dwords; i++)
374 to[i] = from[i];
375}
376
377static void swap_memory(uint32_t *a, uint32_t *b)
378{
379 for(int i = 0; i < g_decode_A_info.nr_dwords; i++)
380 {
381 uint32_t c = a[i];
382 a[i] = b[i];
383 b[i] = c;
384 }
385}
386
387static void shift_left(uint32_t *buf, int nr_bits)
388{
389 for(int i = g_decode_A_info.nr_dwords_m1; i >= 0; i--)
390 buf[i + (nr_bits / 32)] = buf[i];
391 memset(buf, 0, 4 * (nr_bits / 32));
392
393 int size = g_decode_A_info.nr_dwords + (nr_bits + 31) / 32;
394 nr_bits = nr_bits % 32;
395
396 uint32_t acc = 0;
397 for(int i = 0; i < size; i++)
398 {
399 uint32_t new_val = buf[i] << nr_bits | acc;
400 /* WARNING if nr_bits = 0 then the right shift by 32 is undefined and so
401 * the following code could break. The additional AND catches this case
402 * and make sure the result is 0 */
403 acc = ((1 << nr_bits) - 1) & (buf[i] >> (32 - nr_bits));
404 buf[i] = new_val;
405 }
406}
407
408static void xor_big(uint32_t *res, uint32_t *a, uint32_t *b)
409{
410 for(int i = 0; i < g_decode_A_info.nr_dwords_x2; i++)
411 res[i] = a[i] ^ b[i];
412}
413
414static void decode_with_xor(uint32_t *res, uint32_t *key)
415{
416 uint32_t *tmp = malloc(g_decode_A_info.nr_dwords_x8);
417 uint32_t *copy = malloc(g_decode_A_info.nr_dwords_x8);
418 uint32_t *copy_arg = malloc(g_decode_A_info.nr_dwords_x8);
419 uint32_t *tmp2 = malloc(g_decode_A_info.nr_dwords_x8);
420 clear_memory(tmp, g_decode_A_info.nr_dwords_x2);
421 clear_memory(res, g_decode_A_info.nr_dwords);
422 *res = 1;
423 clear_memory(tmp2, g_decode_A_info.nr_dwords);
424 copy_memory(copy_arg, key);
425 copy_memory(copy, (uint32_t *)g_decode_A_info.ptr5);
426
427 for(int i = find_last_bit_set(copy_arg, 1); i; i = find_last_bit_set(copy_arg, 1))
428 {
429 int pos = i - find_last_bit_set(copy, 1);
430 if(pos < 0)
431 {
432 swap_memory(copy_arg, copy);
433 swap_memory(res, tmp2);
434 pos = -pos;
435 }
436 copy_memory(tmp, copy);
437 shift_left(tmp, pos);
438 xor_big(copy_arg, copy_arg, tmp);
439 copy_memory(tmp, tmp2);
440 shift_left(tmp, pos);
441 xor_big(res, res, tmp);
442 }
443 free(tmp);
444 free(copy);
445 free(copy_arg);
446 free(tmp2);
447}
448
449static void shift_left_one(uint32_t *a)
450{
451 int pos = find_last_bit_set(a, 0) / 32 + 1;
452 if(pos <= 0)
453 return;
454 uint32_t v = 0;
455 for(int i = 0; i < pos; i++)
456 {
457 uint32_t new_val = v | a[i] << 1;
458 v = a[i] >> 31;
459 a[i] = new_val;
460 }
461 if(v)
462 a[pos] = v;
463}
464
465
466#if 1
467static void xor_mult(uint32_t *a1, uint32_t *a2, uint32_t *a3)
468{
469 uint32_t *tmp2 = malloc(g_decode_A_info.nr_dwords_x8);
470 clear_memory(tmp2, g_decode_A_info.nr_dwords_x2);
471 copy_memory(tmp2, a3);
472
473 int pos = g_decode_A_info.nr_dwords;
474 uint32_t mask = 1;
475 for(int i = 0; i < 32; i++)
476 {
477 for(int j = 0; j < g_decode_A_info.nr_dwords; j++)
478 {
479 if(a2[j] & mask)
480 for(int k = 0; k < pos; k++)
481 a1[j + k] ^= tmp2[k];
482 }
483 shift_left_one(tmp2);
484 mask <<= 1;
485 pos = find_last_bit_set(tmp2, 0) / 32 + 1;
486 }
487 free(tmp2);
488}
489#else
490static void xor_mult(uint32_t *a1, uint32_t *a2, uint32_t *a3)
491{
492 for(int i = 0; i < 32 * g_decode_A_info.nr_dwords; i++)
493 for(int j = 0; j < 32 * g_decode_A_info.nr_dwords; j++)
494 {
495 int k = i + j;
496 uint32_t v1 = (a2[i / 32] >> (i % 32)) & 1;
497 uint32_t v2 = (a3[j / 32] >> (j % 32)) & 1;
498 a1[k / 32] ^= (v1 * v2) << (k % 32);
499 }
500}
501#endif
502
503static int compare(uint32_t *a, uint32_t *b)
504{
505 return memcmp(a, b, g_decode_A_info.nr_dwords * 4);
506}
507
508static void xor_mult_high(uint32_t *a1, uint32_t *buf, uint32_t *a3)
509{
510 (void) a1;
511 uint32_t *tmp = malloc(g_decode_A_info.nr_dwords_x8);
512 int v4 = g_decode_A_info.field_34;
513 int pos = find_last_bit_set(buf, 0);
514 for(int i = pos - v4; i >= 0; i = find_last_bit_set(buf, 0) - v4)
515 {
516 clear_memory(tmp, g_decode_A_info.nr_dwords_x2);
517 copy_memory(tmp, a3);
518 shift_left(tmp, i);
519 xor_big(buf, buf, tmp);
520 }
521 free(tmp);
522}
523
524static void xor_small(uint32_t *res, uint32_t *a, uint32_t *b)
525{
526 for(int i = 0; i < g_decode_A_info.nr_dwords; i++)
527 res[i] = a[i] ^ b[i];
528}
529
530static void crypto(ptr_bundle_t *a1, ptr_bundle_t *a2)
531{
532 uint32_t *v2 = malloc(g_decode_A_info.nr_dwords_x8);
533 uint32_t *v3 = malloc(g_decode_A_info.nr_dwords_x8);
534 uint32_t *v4 = malloc(g_decode_A_info.nr_dwords_x8);
535 uint32_t *v5 = malloc(g_decode_A_info.nr_dwords_x8);
536 uint32_t *v6 = malloc(g_decode_A_info.nr_dwords_x8);
537 clear_memory(a2->ptrA, g_decode_A_info.nr_dwords);
538 clear_memory(a2->ptrB, g_decode_A_info.nr_dwords);
539 clear_memory(v3, g_decode_A_info.nr_dwords_x2);
540 clear_memory(v6, g_decode_A_info.nr_dwords_x2);
541 clear_memory(v4, g_decode_A_info.nr_dwords_x2);
542 decode_with_xor(v4, a1->ptrA);
543 clear_memory(v5, g_decode_A_info.nr_dwords_x2);
544
545 xor_mult(v5, v4, a1->ptrB);
546 xor_mult_high(v5, v5, g_decode_A_info.ptr5);
547 xor_small(v2, a1->ptrA, v5);
548 xor_small(v4, v2, g_decode_A_info.ptr6);
549 clear_memory(v3, g_decode_A_info.nr_dwords_x2);
550 xor_mult(v3, v2, v2);
551 xor_mult_high(v3, v3, g_decode_A_info.ptr5);
552 xor_small(a2->ptrA, v4, v3);
553 clear_memory(v5, g_decode_A_info.nr_dwords_x2);
554 xor_small(v4, v2, g_xor_key);
555 xor_mult(v5, v4, a2->ptrA);
556 xor_mult_high(v5, v5, g_decode_A_info.ptr5);
557 clear_memory(v6, g_decode_A_info.nr_dwords_x2);
558 xor_mult(v6, a1->ptrA, a1->ptrA);
559 xor_mult_high(v6, v6, g_decode_A_info.ptr5);
560 xor_small(a2->ptrB, v5, v6);
561 free(v2);
562 free(v3);
563 free(v4);
564 free(v5);
565 free(v6);
566}
567
568static void crypto2(ptr_bundle_t *a1, ptr_bundle_t *a2, ptr_bundle_t *a3)
569{
570 uint32_t *v3 = malloc(g_decode_A_info.nr_dwords_x8);
571 uint32_t *v4 = malloc(g_decode_A_info.nr_dwords_x8);
572 uint32_t *v5 = malloc(g_decode_A_info.nr_dwords_x8);
573 uint32_t *v6 = malloc(g_decode_A_info.nr_dwords_x8);
574 uint32_t *v7 = malloc(g_decode_A_info.nr_dwords_x8);
575 clear_memory(a3->ptrA, g_decode_A_info.nr_dwords);
576 clear_memory(a3->ptrB, g_decode_A_info.nr_dwords);
577 clear_memory(v4, g_decode_A_info.nr_dwords_x2);
578 clear_memory(v7, g_decode_A_info.nr_dwords_x2);
579 xor_small(v5, a1->ptrB, a2->ptrB);
580 xor_small(v6, a1->ptrA, a2->ptrA);
581 decode_with_xor(v7, v6);
582 clear_memory(v3, g_decode_A_info.nr_dwords_x2);
583 xor_mult(v3, v7, v5);
584 xor_mult_high(v3, v3, g_decode_A_info.ptr5);
585 xor_small(v5, v3, g_decode_A_info.ptr6);
586 clear_memory(v4, g_decode_A_info.nr_dwords_x2);
587 xor_mult(v4, v3, v3);
588 xor_mult_high(v4, v4, g_decode_A_info.ptr5);
589 xor_small(v7, v5, v4);
590 xor_small(a3->ptrA, v7, v6);
591 xor_small(v5, a1->ptrA, a3->ptrA);
592 xor_small(v6, a3->ptrA, a1->ptrB);
593 clear_memory(v7, g_decode_A_info.nr_dwords_x2);
594 xor_mult(v7, v5, v3);
595 xor_mult_high(v7, v7, g_decode_A_info.ptr5);
596 xor_small(a3->ptrB, v7, v6);
597 free(v3);
598 free(v4);
599 free(v5);
600 free(v6);
601 free(v7);
602}
603
604static int crypto3(uint32_t *a1, ptr_bundle_t *ptrs_alt, ptr_bundle_t *ptrs)
605{
606 ptr_bundle_t ptrs_others;
607
608 ptrs_others.ptrA = malloc(g_decode_A_info.size);
609 ptrs_others.ptrB = malloc(g_decode_A_info.size);
610 clear_memory(ptrs->ptrA, g_decode_A_info.nr_dwords);
611 clear_memory(ptrs->ptrB, g_decode_A_info.nr_dwords);
612 clear_memory(ptrs_others.ptrA, g_decode_A_info.nr_dwords);
613 clear_memory(ptrs_others.ptrB, g_decode_A_info.nr_dwords);
614 int pos = find_last_bit_set(a1, 1);
615
616 copy_memory(ptrs_others.ptrA, ptrs_alt->ptrA);
617 copy_memory(ptrs_others.ptrB, ptrs_alt->ptrB);
618 for(int bit = (pos % 32) - 1; bit >= 0; bit--)
619 {
620 crypto(&ptrs_others, ptrs);
621 copy_memory(ptrs_others.ptrA, ptrs->ptrA);
622 copy_memory(ptrs_others.ptrB, ptrs->ptrB);
623 if(a1[pos / 32] & (1 << bit))
624 {
625 crypto2(&ptrs_others, ptrs_alt, ptrs);
626 copy_memory(ptrs_others.ptrA, ptrs->ptrA);
627 copy_memory(ptrs_others.ptrB, ptrs->ptrB);
628 }
629 }
630 for(int i = pos / 32 - 1; i >= 0; i--)
631 {
632 for(int bit = 31; bit >= 0; bit--)
633 {
634 crypto(&ptrs_others, ptrs);
635 copy_memory(ptrs_others.ptrA, ptrs->ptrA);
636 copy_memory(ptrs_others.ptrB, ptrs->ptrB);
637 if(a1[i] & (1 << bit))
638 {
639 crypto2(&ptrs_others, ptrs_alt, ptrs);
640 copy_memory(ptrs_others.ptrA, ptrs->ptrA);
641 copy_memory(ptrs_others.ptrB, ptrs->ptrB);
642 }
643 }
644 }
645 copy_memory(ptrs->ptrA, ptrs_others.ptrA);
646 copy_memory(ptrs->ptrB, ptrs_others.ptrB);
647 free(ptrs_others.ptrA);
648 free(ptrs_others.ptrB);
649 return 0;
650}
651
652static int crypto4(uint8_t *a1, ptr_bundle_t *ptrs, uint32_t *a3)
653{
654 ptr_bundle_t ptrs_others;
655
656 ptrs_others.ptrA = malloc(g_decode_A_info.size);
657 ptrs_others.ptrB = malloc(g_decode_A_info.size);
658 clear_memory(ptrs_others.ptrA, g_decode_A_info.nr_dwords);
659 clear_memory(ptrs_others.ptrB, g_decode_A_info.nr_dwords);
660 int ret = crypto3(a3, ptrs, &ptrs_others);
661 if(ret == 0)
662 xor_with_ptrs(a1, &ptrs_others);
663 free(ptrs_others.ptrA);
664 free(ptrs_others.ptrB);
665 return ret;
666}
667
668static int crypto_bits(uint32_t *buf, int a2)
669{
670 clear_memory(buf, g_decode_A_info.nr_dwords);
671 g_decode_A_info.field_34 = 0;
672 if(a2 == 4)
673 {
674 set_bit(0, buf);
675 set_bit(74, buf);
676 set_bit(233, buf);
677 g_decode_A_info.field_34 = 233;
678 return 0;
679 }
680 else if (a2 == 5)
681 {
682 set_bit(0, buf);
683 set_bit(3, buf);
684 set_bit(6, buf);
685 set_bit(7, buf);
686 set_bit(163, buf);
687 g_decode_A_info.field_34 = 163;
688 return 0;
689 }
690 else
691 return 1;
692}
693
694static int crypto_bits_copy(ptr_bundle_t *a1, char a2)
695{
696 int ret = crypto_bits(g_decode_A_info.ptr5, a2);
697 if(ret) return ret;
698 if(a2 == 4)
699 {
700 copy_memory(a1->ptrA, g_crypto_table);
701 copy_memory(a1->ptrB, g_crypto_table2);
702 copy_memory(g_decode_A_info.ptr6, g_crypto_data);
703 copy_memory(g_decode_A_info.ptr7, g_crypto_key6);
704 return 0;
705 }
706 else if ( a2 == 5 )
707 {
708 copy_memory(a1->ptrA, g_crypto_key3);
709 copy_memory(a1->ptrB, g_crypto_key4);
710 copy_memory(g_decode_A_info.ptr6, g_crypto_data3);
711 copy_memory(g_decode_A_info.ptr7, g_crypto_key5);
712 return 0;
713 }
714 else
715 return 1;
716}
717
718static void create_guid(void *uid, int bit_size)
719{
720 uint8_t *p = uid;
721 for(int i = 0; i < bit_size / 8; i++)
722 p[i] = rand() % 256;
723}
724
725static int process_block_B(uint8_t block[512])
726{
727 cprintf(BLUE, "Block B\n");
728 decode_block_B(block + 3, g_subblock_A + 4, 489);
729 cprintf_field(" Word: ", "%d ", *(uint16_t *)(block + 3));
730 check_field(*(uint16_t *)(block + 3), 1, "Ok\n", "Mismatch\n");
731
732 int ret = check_block(block, block + 492, 492);
733 cprintf(GREEN, " Check: ");
734 check_field(ret, 0, "Pass\n", "Fail\n");
735
736 g_decode_buffer3 = malloc(g_decode_A_info.size);
737 memset(g_decode_buffer3, 0, g_decode_A_info.size);
738 int offset = *(uint16_t *)(block + 13) + 16;
739 memcpy(g_decode_buffer3, &block[offset], g_decode_A_info.nr_bytes2);
740
741 return 0;
742}
743
744static int do_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB,
745 uint8_t *unk, uint8_t *unk2, uint8_t *blo)
746{
747 (void) size;
748 uint8_t smallblock[512];
749 uint8_t bigblock[1024];
750
751 memset(smallblock, 0, sizeof(smallblock));
752 memset(bigblock, 0, sizeof(bigblock));
753
754 uint8_t ba = buf[0x1ee] & 0xf;
755 uint8_t bb = buf[0x1fe] & 0xf;
756
757 cprintf_field(" Block A: ", "%d\n", ba + 2);
758 cprintf(" Block B: ", "%d\n", ba + bb + 5);
759
760 *blockA = buf[494] & 0xf;
761 *blockB = buf[510] & 0xf;
762 memcpy(bigblock, &buf[512 * (*blockA + 2)], sizeof(bigblock));
763
764 int ret = process_block_A(bigblock);
765 continue_the_force(ret);
766
767 memcpy(smallblock, &buf[512 * (*blockA + *blockB + 5)], sizeof(smallblock));
768 ret = process_block_B(smallblock);
769 continue_the_force(ret);
770
771 cprintf(BLUE, "Main\n");
772
773 // WARNING you need more that 48 because 17+32 > 48 !! (see code below) */
774 uint8_t smallbuf[50];
775 memcpy(smallbuf, buf + 42, sizeof(smallbuf));
776 cprintf_field(" Byte: ", "%d ", smallbuf[16]);
777 check_field(smallbuf[16], 3, "Ok\n", "Mismatch\n");
778
779 ptr_bundle_t ptrs;
780 ptrs.ptrA = malloc(g_decode_A_info.size);
781 ptrs.ptrB = malloc(g_decode_A_info.size);
782 memset(ptrs.ptrA, 0, g_decode_A_info.size);
783 memset(ptrs.ptrB, 0, g_decode_A_info.size);
784 memcpy(ptrs.ptrA, buf + 91, g_decode_A_info.nr_bytes2);
785 memcpy(ptrs.ptrB, buf + 91 + g_decode_A_info.nr_bytes2, g_decode_A_info.nr_bytes2);
786
787 ret = crypto_bits_copy(&g_decode_A_info.ptr1, g_crypto_info_byte);
788 cprintf(GREEN, " Crypto bits copy: ");
789 check_field(ret, 0, "Pass\n", "Fail\n");
790
791 ret = crypto4(smallbuf + 17, &ptrs, g_decode_buffer3);
792 cprintf(GREEN, " Crypto 4: ");
793 check_field(ret, 0, "Pass\n", "Fail\n");
794
795 memcpy(unk2, &smallbuf[17], 32);
796 int offset = g_decode_A_info.nr_words + 91;
797
798 decode_block_with_swap(unk2, 0, &buf[offset], 512 - offset, g_perm_B);
799
800 int pos = *(uint16_t *)&buf[offset];
801 cprintf_field(" Word: ", "%d ", pos);
802 int tmp = g_decode_A_info.nr_words2 + 199;
803 check_field(pos, 510 - tmp, "Ok\n", "Mismatch\n");
804
805 uint8_t midbuf[108];
806 memcpy(midbuf, &buf[pos + offset + 2], sizeof(midbuf));
807
808 cprintf_field(" Byte: ", "%d ", midbuf[0]);
809 check_field(midbuf[0], 2, "Ok\n", "Invalid\n");
810 cprintf_field(" DWord: ", "%d ", *(uint32_t *)&midbuf[1]);
811 check_field(*(uint32_t *)&midbuf[1], 2056, "Ok\n", "Invalid\n");
812 cprintf_field(" DWord: ", "%d ", *(uint32_t *)&midbuf[5]);
813 check_field(*(uint32_t *)&midbuf[5], 8, "Ok\n", "Invalid\n");
814 cprintf_field(" Byte: ", "%d ", midbuf[41]);
815 check_field(midbuf[41], 190, "Ok\n", "Invalid\n");
816
817 memset(blo, 0, 512);
818 create_guid(smallblock, 3808);
819 memcpy(smallblock + 476, midbuf + 42, 16);
820 compute_checksum(smallblock, 492, blo + 492);
821 int bsz = blo[500];
822 memcpy(blo, smallblock, bsz);
823 memcpy(blo + bsz, midbuf + 42, 16);
824 memcpy(blo + bsz + 16, smallblock + bsz, 476 - bsz);
825
826 decode_block_with_perm(blo + 492, 16, blo, 492, g_perm_B);
827 ret = check_block(buf + 42, midbuf + 88, 450);
828 cprintf(GREEN, " Decode block: ");
829 check_field(ret, 0, "Pass\n", "Fail\n");
830
831 ret = memcmp(g_subblock_A + 4, midbuf + 9, 16);
832 cprintf(GREEN, " Compare: ");
833 check_field(ret, 0, "Pass\n", "Fail\n");
834
835 uint8_t zero[16];
836 memset(zero, 0, sizeof(zero));
837 ret = memcmp(unk, zero, sizeof(zero));
838 cprintf(GREEN, " Sanity: ");
839 check_field(ret, 0, "Pass\n", "Fail\n");
840
841 /*
842 ret = memcmp(midbuf + 25, zero, sizeof(zero));
843 cprintf(GREEN, " Sanity: ");
844 check_field(ret, 0, "Pass\n", "Fail\n");
845 */
846
847 return 0;
848}
849
850static int do_sthg_fwu_v3(uint8_t *buf, int *size, uint8_t *unk, uint8_t *block)
851{
852 uint8_t blockA;
853 uint8_t blockB;
854 uint8_t unk2[32];
855 memset(unk2, 0, sizeof(unk2));
856 int ret = do_fwu_v3(*size, buf, &blockA, &blockB, unk, unk2, block);
857 continue_the_force(ret);
858
859 *size -= 2048;
860 uint8_t *tmpbuf = malloc(*size);
861 memset(tmpbuf, 0, *size);
862 int offsetA = (blockA + 1) << 9;
863 int offsetB = (blockB + 1) << 9;
864 memcpy(tmpbuf, buf + 512, offsetA);
865 memcpy(tmpbuf + offsetA, buf + offsetA + 1536, offsetB);
866 memcpy(tmpbuf + offsetA + offsetB,
867 buf + offsetA + 1536 + offsetB + 512, *size - offsetA - offsetB);
868 compute_perm(unk2, 32, g_perm_B);
869 decode_perm(tmpbuf, *size, g_perm_B);
870 memcpy(buf, tmpbuf, *size);
871
872 return 0;
873}
874
875static int do_fwu(uint8_t *buf, int size)
876{
877 struct fwu_hdr_t *hdr = (void *)buf;
878
879 if(size < (int)sizeof(struct fwu_hdr_t))
880 {
881 cprintf(GREY, "File too small\n");
882 return 1;
883 }
884 cprintf(BLUE, "Header\n");
885 cprintf(GREEN, " Signature:");
886 for(int i = 0; i < FWU_SIG_SIZE; i++)
887 cprintf(YELLOW, " %02x", hdr->sig[i]);
888 if(memcmp(hdr->sig, g_fwu_signature, FWU_SIG_SIZE) == 0)
889 cprintf(RED, " Ok\n");
890 else
891 {
892 cprintf(RED, " Mismatch\n");
893 let_the_force_flow(__LINE__);
894 }
895
896 cprintf_field(" FW size: ", "%d ", hdr->fw_size);
897 if((int)hdr->fw_size == size)
898 cprintf(RED, " Ok\n");
899 else if((int)hdr->fw_size < size)
900 cprintf(RED, " Ok (file greater than firmware)\n");
901 else
902 {
903 cprintf(RED, " Error (file too small)\n");
904 let_the_force_flow(__LINE__);
905 }
906
907 cprintf_field(" Block size: ", "%d ", hdr->block_size);
908 check_field(hdr->block_size, FWU_BLOCK_SIZE, "Ok\n", "Invalid\n");
909
910 cprintf_field(" Version: ", "%x ", hdr->version);
911 int ver = get_version(buf, size);
912 if(ver < 0)
913 {
914 cprintf(RED, "(Unknown)\n");
915 return -1;
916 }
917 else
918 cprintf(RED, "(Ver. %d)\n", g_version[ver].version);
919
920 cprintf_field(" Unknown: ", "0x%x ", hdr->unk);
921 check_field(hdr->unk, g_version[ver].unk, "Ok\n", "Invalid\n");
922
923 cprintf(GREEN, " Signature:");
924 for(int i = 0; i < FWU_SIG_SIZE; i++)
925 cprintf(YELLOW, " %02x", hdr->sig2[i]);
926 if(memcmp(hdr->sig2, g_version[ver].sig2, FWU_SIG_SIZE) == 0)
927 cprintf(RED, " Ok\n");
928 else
929 {
930 cprintf(RED, " Mismatch\n");
931 let_the_force_flow(__LINE__);
932 }
933
934 if(g_version[ver].version == 3)
935 {
936 uint8_t unk[32];
937 memset(unk, 0, sizeof(unk));
938 uint8_t block[512];
939 memset(block, 0, sizeof(block));
940 int ret = do_sthg_fwu_v3(buf, &size, unk, block);
941 continue_the_force(ret);
942
943 if(g_out_prefix)
944 {
945 FILE *f = fopen(g_out_prefix, "wb");
946 if(f)
947 {
948 fwrite(buf, size, 1, f);
949 fclose(f);
950 }
951 }
952 }
953
954 return 0;
955}
956
957static bool check_fwu(uint8_t *buf, int size)
958{
959 struct fwu_hdr_t *hdr = (void *)buf;
960
961 if(size < (int)sizeof(struct fwu_hdr_t))
962 return false;
963 return memcmp(hdr->sig, g_fwu_signature, FWU_SIG_SIZE) == 0;
964}
965
966/**
967 * AFI
968 *
969 * part of this work comes from s1mp3/s1fwx
970 **/
971
972#define AFI_ENTRIES 126
973#define AFI_SIG_SIZE 4
974
975struct afi_hdr_t
976{
977 uint8_t sig[AFI_SIG_SIZE];
978 uint16_t vendor_id;
979 uint16_t product_id;
980 uint8_t ver_id[2];
981 uint8_t ext_ver_id[2];
982 uint8_t year[2];
983 uint8_t month;
984 uint8_t day;
985 uint32_t afi_size;
986 uint32_t res[3];
987} __attribute__((packed));
988
989struct afi_entry_t
990{
991 char name[8];
992 char ext[3];
993 char type;
994 uint32_t addr;
995 uint32_t offset;
996 uint32_t size;
997 char desc[4];
998 uint32_t checksum;
999} __attribute__((packed));
1000
1001struct afi_post_hdr_t
1002{
1003 uint8_t res[28];
1004 uint32_t checksum;
1005} __attribute__((packed));
1006
1007struct afi_t
1008{
1009 struct afi_hdr_t hdr;
1010 struct afi_entry_t entry[AFI_ENTRIES];
1011 struct afi_post_hdr_t post;
1012};
1013
1014#define AFI_ENTRY_BREC 'B'
1015#define AFI_ENTRY_FWSC 'F'
1016#define AFI_ENTRY_ADFUS 'A'
1017#define AFI_ENTRY_FW 'I'
1018
1019#define AFI_ENTRY_DLADR_BREC 0x00000006 // 'B'
1020#define AFI_ENTRY_DLADR_FWSC 0x00020008 // 'F'
1021#define AFI_ENTRY_DLADR_ADFUS 0x000C0008 // 'A'
1022#define AFI_ENTRY_DLADR_ADFU 0x00000000 // 'U'
1023#define AFI_ENTRY_DLADR_FW 0x00000011 // 'I'
1024
1025const uint8_t g_afi_signature[AFI_SIG_SIZE] =
1026{
1027 'A', 'F', 'I', 0
1028};
1029
1030static uint32_t afi_checksum(void *ptr, int size)
1031{
1032 uint32_t crc = 0;
1033 uint32_t *cp = ptr;
1034 for(; size >= 4; size -= 4)
1035 crc += *cp++;
1036 if(size == 1)
1037 crc += *(uint8_t *)cp;
1038 else if(size == 2)
1039 crc += *(uint16_t *)cp;
1040 else if(size == 3)
1041 crc += *(uint16_t *)cp + ((*(uint8_t *)(cp + 2)) << 16);
1042 return crc;
1043}
1044
1045static void build_filename(char buf[16], struct afi_entry_t *ent)
1046{
1047 int pos = 0;
1048 for(int i = 0; i < 8 && ent->name[i] != ' '; i++)
1049 buf[pos++] = ent->name[i];
1050 buf[pos++] = '.';
1051 for(int i = 0; i < 3 && ent->ext[i] != ' '; i++)
1052 buf[pos++] = ent->ext[i];
1053 buf[pos] = 0;
1054}
1055
1056static int do_afi(uint8_t *buf, int size)
1057{
1058 struct afi_t *afi = (void *)buf;
1059
1060 if(size < (int)sizeof(struct afi_t))
1061 {
1062 cprintf(GREY, "File too small\n");
1063 return 1;
1064 }
1065 cprintf(BLUE, "Header\n");
1066 cprintf(GREEN, " Signature:");
1067 for(int i = 0; i < AFI_SIG_SIZE; i++)
1068 cprintf(YELLOW, " %02x", afi->hdr.sig[i]);
1069 if(memcmp(afi->hdr.sig, g_afi_signature, AFI_SIG_SIZE) == 0)
1070 cprintf(RED, " Ok\n");
1071 else
1072 {
1073 cprintf(RED, " Mismatch\n");
1074 let_the_force_flow(__LINE__);
1075 }
1076
1077 cprintf_field(" Vendor ID: ", "0x%x\n", afi->hdr.vendor_id);
1078 cprintf_field(" Product ID: ", "0x%x\n", afi->hdr.product_id);
1079 cprintf_field(" Version: ", "%x.%x\n", afi->hdr.ver_id[0], afi->hdr.ver_id[1]);
1080 cprintf_field(" Ext Version: ", "%x.%x\n", afi->hdr.ext_ver_id[0],
1081 afi->hdr.ext_ver_id[1]);
1082 cprintf_field(" Date: ", "%x/%x/%x%x\n", afi->hdr.day, afi->hdr.month,
1083 afi->hdr.year[0], afi->hdr.year[1]);
1084
1085 cprintf_field(" AFI size: ", "%d ", afi->hdr.afi_size);
1086 if((int)afi->hdr.afi_size == size)
1087 cprintf(RED, " Ok\n");
1088 else if((int)afi->hdr.afi_size < size)
1089 cprintf(RED, " Ok (file greater than archive)\n");
1090 else
1091 {
1092 cprintf(RED, " Error (file too small)\n");
1093 let_the_force_flow(__LINE__);
1094 }
1095
1096 cprintf_field(" Reserved: ", "%x %x %x\n", afi->hdr.res[0],
1097 afi->hdr.res[1], afi->hdr.res[2]);
1098
1099 cprintf(BLUE, "Entries\n");
1100 for(int i = 0; i < AFI_ENTRIES; i++)
1101 {
1102 if(afi->entry[i].name[0] == 0)
1103 continue;
1104 struct afi_entry_t *entry = &afi->entry[i];
1105 char filename[16];
1106 build_filename(filename, entry);
1107 cprintf(RED, " %s\n", filename);
1108 cprintf_field(" Type: ", "%02x", entry->type);
1109 if(isprint(entry->type))
1110 cprintf(RED, " %c", entry->type);
1111 printf("\n");
1112 cprintf_field(" Addr: ", "0x%x\n", entry->addr);
1113 cprintf_field(" Offset: ", "0x%x\n", entry->offset);
1114 cprintf_field(" Size: ", "0x%x\n", entry->size);
1115 cprintf_field(" Desc: ", "%.4s\n", entry->desc);
1116 cprintf_field(" Checksum: ", "0x%x ", entry->checksum);
1117 uint32_t chk = afi_checksum(buf + entry->offset, entry->size);
1118 cprintf(RED, "%s\n", chk == entry->checksum ? "Ok" : "Mismatch");
1119
1120 if(g_out_prefix)
1121 {
1122 char *name = malloc(strlen(g_out_prefix) + strlen(filename) + 16);
1123 sprintf(name, "%s%s", g_out_prefix, filename);
1124 FILE *f = fopen(name, "wb");
1125 if(f)
1126 {
1127 fwrite(buf + entry->offset, entry->size, 1, f);
1128 fclose(f);
1129 }
1130 }
1131 }
1132
1133 cprintf(BLUE, "Post Header\n");
1134 cprintf_field(" Checksum: ", "%x ", afi->post.checksum);
1135 uint32_t chk = afi_checksum(buf, sizeof(struct afi_t) - 4);
1136 cprintf(RED, "%s\n", chk == afi->post.checksum ? "Ok" : "Mismatch");
1137
1138 return 0;
1139}
1140
1141static bool check_afi(uint8_t *buf, int size)
1142{
1143 struct afi_hdr_t *hdr = (void *)buf;
1144
1145 if(size < (int)sizeof(struct afi_hdr_t))
1146 return false;
1147 return memcmp(hdr->sig, g_afi_signature, AFI_SIG_SIZE) == 0;
1148}
1149
1150/**
1151 * FW
1152 **/
1153
1154#define FW_SIG_SIZE 4
1155
1156#define FW_ENTRIES 240
1157
1158struct fw_entry_t
1159{
1160 char name[8];
1161 char ext[3];
1162 uint8_t attr;
1163 uint8_t res[2];
1164 uint16_t version;
1165 uint32_t block_offset; // offset shift by 9
1166 uint32_t size;
1167 uint32_t unk;
1168 uint32_t checksum;
1169} __attribute__((packed));
1170
1171struct fw_hdr_t
1172{
1173 uint8_t sig[FW_SIG_SIZE];
1174 uint32_t res[4];
1175 uint8_t year[2];
1176 uint8_t month;
1177 uint8_t day;
1178 uint16_t usb_vid;
1179 uint16_t usb_pid;
1180 uint32_t checksum;
1181 char productor[16];
1182 char str2[16];
1183 char str3[32];
1184 char dev_name[32];
1185 uint8_t res2[8 * 16];
1186 char usb_name1[8];
1187 char usb_name2[8];
1188 char res3[4 * 16 + 1];
1189 char mtp_name1[33];
1190 char mtp_name2[33];
1191 char mtp_ver[33];
1192 uint16_t mtp_vid;
1193 uint16_t mtp_pid;
1194 char fw_ver[64];
1195 uint32_t res4[2];
1196
1197 struct fw_entry_t entry[FW_ENTRIES];
1198} __attribute__((packed));
1199
1200const uint8_t g_fw_signature[FW_SIG_SIZE] =
1201{
1202 0x55, 0xaa, 0xf2, 0x0f
1203};
1204
1205static void build_filename_fw(char buf[16], struct fw_entry_t *ent)
1206{
1207 int pos = 0;
1208 for(int i = 0; i < 8 && ent->name[i] != ' '; i++)
1209 buf[pos++] = ent->name[i];
1210 buf[pos++] = '.';
1211 for(int i = 0; i < 3 && ent->ext[i] != ' '; i++)
1212 buf[pos++] = ent->ext[i];
1213 buf[pos] = 0;
1214}
1215
1216static int do_fw(uint8_t *buf, int size)
1217{
1218 struct fw_hdr_t *hdr = (void *)buf;
1219
1220 if(size < (int)sizeof(struct fw_hdr_t))
1221 {
1222 cprintf(GREY, "File too small\n");
1223 return 1;
1224 }
1225 cprintf(BLUE, "Header\n");
1226 cprintf(GREEN, " Signature:");
1227 for(int i = 0; i < FW_SIG_SIZE; i++)
1228 cprintf(YELLOW, " %02x", hdr->sig[i]);
1229 if(memcmp(hdr->sig, g_fw_signature, FW_SIG_SIZE) == 0)
1230 cprintf(RED, " Ok\n");
1231 else
1232 {
1233 cprintf(RED, " Mismatch\n");
1234 let_the_force_flow(__LINE__);
1235 }
1236
1237 cprintf_field(" USB VID: ", "0x%x\n", hdr->usb_vid);
1238 cprintf_field(" USB PID: ", "0x%x\n", hdr->usb_pid);
1239 cprintf_field(" Date: ", "%x/%x/%x%x\n", hdr->day, hdr->month, hdr->year[0], hdr->year[1]);
1240 cprintf_field(" Checksum: ", "%x\n", hdr->checksum);
1241 cprintf_field(" Productor: ", "%.16s\n", hdr->productor);
1242 cprintf_field(" String 2: ", "%.16s\n", hdr->str2);
1243 cprintf_field(" String 3: ", "%.32s\n", hdr->str3);
1244 cprintf_field(" Device Name: ", "%.32s\n", hdr->dev_name);
1245 cprintf(GREEN, " Unknown:\n");
1246 for(int i = 0; i < 8; i++)
1247 {
1248 cprintf(YELLOW, " ");
1249 for(int j = 0; j < 16; j++)
1250 cprintf(YELLOW, "%02x ", hdr->res2[i * 16 + j]);
1251 cprintf(YELLOW, "\n");
1252 }
1253 cprintf_field(" USB Name 1: ", "%.8s\n", hdr->usb_name1);
1254 cprintf_field(" USB Name 2: ", "%.8s\n", hdr->usb_name2);
1255 cprintf_field(" MTP Name 1: ", "%.32s\n", hdr->mtp_name1);
1256 cprintf_field(" MTP Name 2: ", "%.32s\n", hdr->mtp_name2);
1257 cprintf_field(" MTP Version: ", "%.32s\n", hdr->mtp_ver);
1258
1259 cprintf_field(" MTP VID: ", "0x%x\n", hdr->mtp_vid);
1260 cprintf_field(" MTP PID: ", "0x%x\n", hdr->mtp_pid);
1261 cprintf_field(" FW Version: ", "%.64s\n", hdr->fw_ver);
1262
1263 cprintf(BLUE, "Entries\n");
1264 for(int i = 0; i < AFI_ENTRIES; i++)
1265 {
1266 if(hdr->entry[i].name[0] == 0)
1267 continue;
1268 struct fw_entry_t *entry = &hdr->entry[i];
1269 char filename[16];
1270 build_filename_fw(filename, entry);
1271 cprintf(RED, " %s\n", filename);
1272 cprintf_field(" Attr: ", "%02x\n", entry->attr);
1273 cprintf_field(" Offset: ", "0x%x\n", entry->block_offset << 9);
1274 cprintf_field(" Size: ", "0x%x\n", entry->size);
1275 cprintf_field(" Unknown: ", "%x\n", entry->unk);
1276 cprintf_field(" Checksum: ", "0x%x ", entry->checksum);
1277 uint32_t chk = afi_checksum(buf + (entry->block_offset << 9), entry->size);
1278 cprintf(RED, "%s\n", chk == entry->checksum ? "Ok" : "Mismatch");
1279 if(g_out_prefix)
1280 {
1281 char *name = malloc(strlen(g_out_prefix) + strlen(filename) + 16);
1282 sprintf(name, "%s%s", g_out_prefix, filename);
1283 FILE *f = fopen(name, "wb");
1284 if(f)
1285 {
1286 fwrite(buf + (entry->block_offset << 9), entry->size, 1, f);
1287 fclose(f);
1288 }
1289 }
1290 }
1291
1292 return 0;
1293}
1294
1295static bool check_fw(uint8_t *buf, int size)
1296{
1297 struct fw_hdr_t *hdr = (void *)buf;
1298
1299 if(size < (int)sizeof(struct fw_hdr_t))
1300 return false;
1301 return memcmp(hdr->sig, g_fw_signature, FW_SIG_SIZE) == 0;
1302}
1303
1304static void usage(void)
1305{
1306 printf("Usage: atjboottool [options] firmware\n");
1307 printf("Options:\n");
1308 printf(" -o <prefix>\tSet output prefix\n");
1309 printf(" -f/--force\tForce to continue on errors\n");
1310 printf(" -?/--help\tDisplay this message\n");
1311 printf(" -d/--debug\tDisplay debug messages\n");
1312 printf(" -c/--no-color\tDisable color output\n");
1313 printf(" --fwu\tUnpack a FWU firmware file\n");
1314 printf(" --afi\tUnpack a AFI archive file\n");
1315 printf(" --fw\tUnpack a FW archive file\n");
1316 printf("The default is to try to guess the format.\n");
1317 printf("If several formats are specified, all are tried.\n");
1318 exit(1);
1319}
1320
1321int main(int argc, char **argv)
1322{
1323 bool try_fwu = false;
1324 bool try_afi = false;
1325 bool try_fw = false;
1326
1327 while(1)
1328 {
1329 static struct option long_options[] =
1330 {
1331 {"help", no_argument, 0, '?'},
1332 {"debug", no_argument, 0, 'd'},
1333 {"no-color", no_argument, 0, 'c'},
1334 {"force", no_argument, 0, 'f'},
1335 {"fwu", no_argument, 0, 'u'},
1336 {"afi", no_argument, 0, 'a'},
1337 {"fw", no_argument, 0, 'w'},
1338 {0, 0, 0, 0}
1339 };
1340
1341 int c = getopt_long(argc, argv, "?dcfo:a1", long_options, NULL);
1342 if(c == -1)
1343 break;
1344 switch(c)
1345 {
1346 case -1:
1347 break;
1348 case 'c':
1349 enable_color(false);
1350 break;
1351 case 'd':
1352 g_debug = true;
1353 break;
1354 case 'f':
1355 g_force = true;
1356 break;
1357 case '?':
1358 usage();
1359 break;
1360 case 'o':
1361 g_out_prefix = optarg;
1362 break;
1363 case 'a':
1364 try_afi = true;
1365 break;
1366 case 'u':
1367 try_fwu = true;
1368 break;
1369 case 'w':
1370 try_fw = true;
1371 break;
1372 default:
1373 abort();
1374 }
1375 }
1376
1377 if(argc - optind != 1)
1378 {
1379 usage();
1380 return 1;
1381 }
1382
1383 FILE *fin = fopen(argv[optind], "r");
1384 if(fin == NULL)
1385 {
1386 perror("Cannot open boot file");
1387 return 1;
1388 }
1389 fseek(fin, 0, SEEK_END);
1390 long size = ftell(fin);
1391 fseek(fin, 0, SEEK_SET);
1392
1393 void *buf = malloc(size);
1394 if(buf == NULL)
1395 {
1396 perror("Cannot allocate memory");
1397 return 1;
1398 }
1399
1400 if(fread(buf, size, 1, fin) != 1)
1401 {
1402 perror("Cannot read file");
1403 return 1;
1404 }
1405
1406 fclose(fin);
1407
1408 int ret = -99;
1409 if(try_fwu || check_fwu(buf, size))
1410 ret = do_fwu(buf, size);
1411 else if(try_afi || check_afi(buf, size))
1412 ret = do_afi(buf, size);
1413 else if(try_fw || check_fw(buf, size))
1414 ret = do_fw(buf, size);
1415 else
1416 {
1417 cprintf(GREY, "No valid format found\n");
1418 ret = 1;
1419 }
1420
1421 if(ret != 0)
1422 {
1423 cprintf(GREY, "Error: %d", ret);
1424 if(!g_force)
1425 cprintf(GREY, " (use --force to force processing)");
1426 printf("\n");
1427 ret = 2;
1428 }
1429 free(buf);
1430
1431 color(OFF);
1432
1433 return ret;
1434}
1435
diff --git a/utils/atj2137/atjboottool/misc.c b/utils/atj2137/atjboottool/misc.c
new file mode 100644
index 0000000000..108235e7fd
--- /dev/null
+++ b/utils/atj2137/atjboottool/misc.c
@@ -0,0 +1,53 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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 <stdlib.h>
22#include <stdio.h>
23#include <time.h>
24#include <ctype.h>
25#include "misc.h"
26
27char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' };
28
29char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' };
30char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' };
31char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' };
32char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' };
33char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
34
35static bool g_color_enable = true;
36
37void *xmalloc(size_t s)
38{
39 void * r = malloc(s);
40 if(!r) bugp("malloc");
41 return r;
42}
43
44void enable_color(bool enable)
45{
46 g_color_enable = enable;
47}
48
49void color(color_t c)
50{
51 if(g_color_enable)
52 printf("%s", (char *)c);
53}
diff --git a/utils/atj2137/atjboottool/misc.h b/utils/atj2137/atjboottool/misc.h
new file mode 100644
index 0000000000..b0658c0d31
--- /dev/null
+++ b/utils/atj2137/atjboottool/misc.h
@@ -0,0 +1,41 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 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 __MISC_H__
22#define __MISC_H__
23
24#include <stdbool.h>
25
26#define _STR(a) #a
27#define STR(a) _STR(a)
28
29#define bug(...) do { fprintf(stderr,"["__FILE__":"STR(__LINE__)"]ERROR: "__VA_ARGS__); exit(1); } while(0)
30#define bugp(...) do { fprintf(stderr, __VA_ARGS__); perror(" "); exit(1); } while(0)
31
32#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
33
34typedef char color_t[];
35
36extern color_t OFF, GREY, RED, GREEN, YELLOW, BLUE;
37void *xmalloc(size_t s);
38void color(color_t c);
39void enable_color(bool enable);
40
41#endif /* __MISC_H__ */