diff options
Diffstat (limited to 'tools/rkw.c')
-rw-r--r-- | tools/rkw.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/tools/rkw.c b/tools/rkw.c new file mode 100644 index 0000000000..db86b4f748 --- /dev/null +++ b/tools/rkw.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2012 Marcin Bukat | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version 2 | ||
14 | * of the License, or (at your option) any later version. | ||
15 | * | ||
16 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
17 | * KIND, either express or implied. | ||
18 | * | ||
19 | ****************************************************************************/ | ||
20 | |||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <string.h> | ||
24 | #include <stdint.h> | ||
25 | |||
26 | #define RKLD_MAGIC 0x4c44524b | ||
27 | #define RKW_HEADER_SIZE 0x2c | ||
28 | |||
29 | /* slightly modified version from crc32.c in rockbox */ | ||
30 | static uint32_t rkw_crc32(const void *src, uint32_t len) | ||
31 | { | ||
32 | const unsigned char *buf = (const unsigned char *)src; | ||
33 | |||
34 | /* polynomial 0x04c10db7 */ | ||
35 | static const uint32_t crc32_lookup[16] = | ||
36 | { /* lookup table for 4 bits at a time is affordable */ | ||
37 | 0x00000000, 0x04C10DB7, 0x09821B6E, 0x0D4316D9, | ||
38 | 0x130436DC, 0x17C53B6B, 0x1A862DB2, 0x1E472005, | ||
39 | 0x26086DB8, 0x22C9600F, 0x2F8A76D6, 0x2B4B7B61, | ||
40 | 0x350C5B64, 0x31CD56D3, 0x3C8E400A, 0x384F4DBD | ||
41 | }; | ||
42 | |||
43 | uint32_t crc32 = 0; | ||
44 | unsigned char byte; | ||
45 | uint32_t t; | ||
46 | |||
47 | while (len--) | ||
48 | { | ||
49 | byte = *buf++; /* get one byte of data */ | ||
50 | |||
51 | /* upper nibble of our data */ | ||
52 | t = crc32 >> 28; /* extract the 4 most significant bits */ | ||
53 | t ^= byte >> 4; /* XOR in 4 bits of data into the extracted bits */ | ||
54 | crc32 <<= 4; /* shift the CRC register left 4 bits */ | ||
55 | crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ | ||
56 | |||
57 | /* lower nibble of our data */ | ||
58 | t = crc32 >> 28; /* extract the 4 most significant bits */ | ||
59 | t ^= byte & 0x0F; /* XOR in 4 bits of data into the extracted bits */ | ||
60 | crc32 <<= 4; /* shift the CRC register left 4 bits */ | ||
61 | crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */ | ||
62 | } | ||
63 | |||
64 | return crc32; | ||
65 | } | ||
66 | |||
67 | static void int2le(unsigned int val, unsigned char* addr) | ||
68 | { | ||
69 | addr[0] = val & 0xFF; | ||
70 | addr[1] = (val >> 8) & 0xff; | ||
71 | addr[2] = (val >> 16) & 0xff; | ||
72 | addr[3] = (val >> 24) & 0xff; | ||
73 | } | ||
74 | |||
75 | int rkw_encode(char *iname, char *oname, unsigned long modelnum) | ||
76 | { | ||
77 | size_t len; | ||
78 | int length; | ||
79 | int rkwlength; | ||
80 | FILE *file; | ||
81 | uint32_t binary_crc, header_crc; | ||
82 | unsigned char *outbuf; | ||
83 | |||
84 | file = fopen(iname, "rb"); | ||
85 | if (!file) | ||
86 | { | ||
87 | perror(iname); | ||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | fseek(file,0,SEEK_END); | ||
92 | length = ftell(file); | ||
93 | |||
94 | fseek(file,0,SEEK_SET); | ||
95 | |||
96 | /* length of the RKW header + binary length + 4 bytes of CRC */ | ||
97 | rkwlength = (length + RKW_HEADER_SIZE + 4); | ||
98 | |||
99 | outbuf = malloc(rkwlength); | ||
100 | |||
101 | if (!outbuf) | ||
102 | { | ||
103 | printf("out of memory!\n"); | ||
104 | fclose(file); | ||
105 | return -1; | ||
106 | } | ||
107 | |||
108 | /* Clear the buffer to zero */ | ||
109 | memset(outbuf, 0, rkwlength); | ||
110 | |||
111 | /* Build the RKW header */ | ||
112 | int2le(RKLD_MAGIC, outbuf); /* magic */ | ||
113 | int2le(RKW_HEADER_SIZE, outbuf+0x04); /* header size */ | ||
114 | int2le(0x60000000, outbuf+0x08); /* base address */ | ||
115 | int2le(0x60000000, outbuf+0x0c); /* load address */ | ||
116 | int2le(0x60000000+length, outbuf+0x10); /* end address */ | ||
117 | int2le(0x6035a5e4, outbuf+0x14); /* points to some unknown struct */ | ||
118 | int2le(modelnum, outbuf+0x18); /* reserved (we abuse the format | ||
119 | * to store modelnum here | ||
120 | */ | ||
121 | int2le(0, outbuf+0x1c); /* reserved */ | ||
122 | int2le(0x60000000, outbuf+0x20); /* entry point */ | ||
123 | int2le(0xe0000000, outbuf+0x24); /* flags */ | ||
124 | |||
125 | header_crc = rkw_crc32(outbuf, RKW_HEADER_SIZE - 4); | ||
126 | |||
127 | int2le(header_crc, outbuf+0x28); /* header CRC */ | ||
128 | |||
129 | /* Copy the binary */ | ||
130 | len = fread(outbuf + RKW_HEADER_SIZE, 1, length, file); | ||
131 | if(len < (size_t)length) | ||
132 | { | ||
133 | perror(iname); | ||
134 | free(outbuf); | ||
135 | fclose(file); | ||
136 | return -2; | ||
137 | } | ||
138 | fclose(file); | ||
139 | |||
140 | /* calc binary CRC and put at the end */ | ||
141 | binary_crc = rkw_crc32 (outbuf + RKW_HEADER_SIZE, length); | ||
142 | int2le(binary_crc, outbuf + rkwlength - 4); | ||
143 | |||
144 | file = fopen(oname, "wb"); | ||
145 | if (!file) | ||
146 | { | ||
147 | perror(oname); | ||
148 | free(outbuf); | ||
149 | return -3; | ||
150 | } | ||
151 | |||
152 | len = fwrite(outbuf, 1, rkwlength, file); | ||
153 | if(len < (size_t)length) | ||
154 | { | ||
155 | perror(oname); | ||
156 | fclose(file); | ||
157 | free(outbuf); | ||
158 | return -4; | ||
159 | } | ||
160 | |||
161 | fclose(file); | ||
162 | free(outbuf); | ||
163 | fprintf(stderr, "File encoded successfully\n" ); | ||
164 | |||
165 | return 0; | ||
166 | } | ||