summaryrefslogtreecommitdiff
path: root/utils/rk27utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rk27utils')
-rw-r--r--utils/rk27utils/README15
-rw-r--r--utils/rk27utils/rkwtool/Makefile7
-rw-r--r--utils/rk27utils/rkwtool/main.c129
-rw-r--r--utils/rk27utils/rkwtool/rkw.c538
-rw-r--r--utils/rk27utils/rkwtool/rkw.h123
5 files changed, 812 insertions, 0 deletions
diff --git a/utils/rk27utils/README b/utils/rk27utils/README
index d0343580b8..802f5a559b 100644
--- a/utils/rk27utils/README
+++ b/utils/rk27utils/README
@@ -36,6 +36,21 @@ rockchip player.
36 36
37You need libusb-1.0 + header files in order to compile this utility. 37You need libusb-1.0 + header files in order to compile this utility.
38 38
39
40rkwtool
41This directory contains tool to inspect and extract content of
42'full' update RKW file.
43
44The RKW file contains specific section which instruct update
45routine of the DAP what to do, custom archive with firmware files,
46images of stage1 and stage2 nand bootloader and Rock27Boot.bin file
47image. Nand bootloader images are stored in scrambled form but
48the tool deciphers it to plain binary during extraction.
49
50More complete descritpion of file format can be found on wiki:
51http://www.rockbox.org/wiki/RKWFileFormat
52
53
39nandextract 54nandextract
40This directory contains quick and dirty tool which allows to extract 55This directory contains quick and dirty tool which allows to extract
41nand bootloader from raw dump of the first nand block. The main reason 56nand bootloader from raw dump of the first nand block. The main reason
diff --git a/utils/rk27utils/rkwtool/Makefile b/utils/rk27utils/rkwtool/Makefile
new file mode 100644
index 0000000000..239733cb87
--- /dev/null
+++ b/utils/rk27utils/rkwtool/Makefile
@@ -0,0 +1,7 @@
1all: rkwtool
2
3rkwtool: rkw.c main.c
4 gcc -g -std=c99 -o $@ -W -Wall $^
5
6clean:
7 rm -fr rkwtool
diff --git a/utils/rk27utils/rkwtool/main.c b/utils/rk27utils/rkwtool/main.c
new file mode 100644
index 0000000000..dacfd9ffab
--- /dev/null
+++ b/utils/rk27utils/rkwtool/main.c
@@ -0,0 +1,129 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2014 by 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 <getopt.h>
22#include <stdbool.h>
23#include <stddef.h>
24#include <stdio.h>
25#include "rkw.h"
26
27#define VERSION "v0.1"
28
29static void banner(void)
30{
31 printf("RKWtool " VERSION " (C) Marcin Bukat 2014\n");
32 printf("This is free software; see the source for copying conditions. There is NO\n");
33 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
34}
35
36static void usage(char *name)
37{
38 banner();
39
40 printf("Usage: %s [-i] [-b] [-e] [-a] [-o prefix] file.rkw\n", name);
41 printf("-i\t\tprint info about RKW file\n");
42 printf("-b\t\textract nand bootloader images (s1.bin and s2.bin)\n");
43 printf("-e\t\textract firmware files stored in RKST section\n");
44 printf("-o prefix\twhen extracting firmware files put it there\n");
45 printf("-a\t\textract additional file(s) (usually Rock27Boot.bin)\n");
46 printf("-A\t\textract all data\n");
47 printf("file.rkw\tRKW file to be processed\n");
48}
49
50int main(int argc, char **argv)
51{
52 int opt;
53 struct rkw_info_t *rkw_info = NULL;
54 char *prefix = NULL;
55 bool info = false;
56 bool extract = false;
57 bool bootloader = false;
58 bool addfile = false;
59
60 while ((opt = getopt(argc, argv, "iebo:aA")) != -1)
61 {
62 switch (opt)
63 {
64 case 'i':
65 info = true;
66 break;
67
68 case 'e':
69 extract = true;
70 break;
71
72 case 'b':
73 bootloader = true;
74 break;
75
76 case 'o':
77 prefix = optarg;
78 break;
79
80 case 'a':
81 addfile = true;
82 break;
83
84 case 'A':
85 extract = true;
86 bootloader = true;
87 addfile = true;
88 break;
89
90 default:
91 usage(argv[0]);
92 break;
93 }
94 }
95
96 if ((argc - optind) != 1 ||
97 (!info && !extract && ! bootloader && !addfile))
98 {
99 usage(argv[0]);
100 return -1;
101 }
102
103 banner();
104
105 rkw_info = rkw_slurp(argv[optind]);
106
107 if (rkw_info)
108 {
109 if (info)
110 {
111 rkrs_list_named_items(rkw_info);
112 rkst_list_named_items(rkw_info);
113 }
114
115 if (extract)
116 unpack_rkst(rkw_info, prefix);
117
118 if (bootloader)
119 unpack_bootloader(rkw_info, prefix);
120
121 if (addfile)
122 unpack_addfile(rkw_info, prefix);
123
124 rkw_free(rkw_info);
125 return 0;
126 }
127
128 return -1;
129}
diff --git a/utils/rk27utils/rkwtool/rkw.c b/utils/rk27utils/rkwtool/rkw.c
new file mode 100644
index 0000000000..eacef87b8e
--- /dev/null
+++ b/utils/rk27utils/rkwtool/rkw.c
@@ -0,0 +1,538 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2014 by 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 <stdint.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <string.h>
26#include <errno.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29
30#include "rkw.h"
31
32const char *section_name[] = {
33 "RKLD",
34 "RKRS",
35 "RKST"
36};
37
38const uint32_t section_magic[] = {
39 RKLD_MAGIC,
40 RKRS_MAGIC,
41 RKST_MAGIC
42};
43
44const char *rkrs_action_name[] = {
45 [act_null] = "null",
46 [act_mkdir] = "mkdir",
47 [act_fcopy] = "fcopy",
48 [act_fsoper] = "fsoper",
49 [act_format] = "format",
50 [act_loader] = "loader",
51 [act_dispbmp] = "dispbmp",
52 [act_dispstr] = "dispstr",
53 [act_setfont] = "setfont",
54 [act_delay] = "delay",
55 [act_system] = "system",
56 [act_readme] = "readme",
57 [act_copyright] = "copyright",
58 [act_select] = "select",
59 [act_restart] = "restart",
60 [act_regkey] = "regkey",
61 [act_version] = "version",
62 [act_freplace] = "freplace",
63 [act_fpreplace] = "fpreplace",
64 [act_fsdel] = "fsdel",
65 [act_space] = "space",
66 [act_addfile] = "addfile",
67 [act_setmem] = "setmem",
68 [act_getmem] = "getmem"
69};
70
71/* scrambling/descrambling reverse engineered by AleMaxx */
72static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
73{
74
75uint8_t key[] = {
76 0x7C, 0x4E, 0x03, 0x04,
77 0x55, 0x05, 0x09, 0x07,
78 0x2D, 0x2C, 0x7B, 0x38,
79 0x17, 0x0D, 0x17, 0x11
80};
81 int i, i3, x, val, idx;
82
83 uint8_t key1[0x100];
84 uint8_t key2[0x100];
85
86 for (i=0; i<0x100; i++) {
87 key1[i] = i;
88 key2[i] = key[i&0xf];
89 }
90
91 i3 = 0;
92 for (i=0; i<0x100; i++) {
93 x = key1[i];
94 i3 = key1[i] + i3;
95 i3 += key2[i];
96 i3 &= 0xff;
97 key1[i] = key1[i3];
98 key1[i3] = x;
99 }
100
101 idx = 0;
102 for (i=0; i<size; i++) {
103 x = key1[(i+1) & 0xff];
104 val = x;
105 idx = (x + idx) & 0xff;
106 key1[(i+1) & 0xff] = key1[idx];
107 key1[idx] = (x & 0xff);
108 val = (key1[(i+1)&0xff] + x) & 0xff;
109 val = key1[val];
110 outpg[i] = val ^ inpg[i];
111 }
112}
113
114/* take path as stored in RKST and convert it to unix path
115 * with optional prefix
116 */
117static char *unixpath(char *path, char *prefix)
118{
119 char *parsed, *ptr;
120 size_t size = 0;
121
122 if (NULL == path)
123 return NULL;
124
125 size = strlen(path) + 1;
126
127 /* full windows path i.e C:\something */
128 if (strlen(path) > 2 && ':' == path[1])
129 path += 3;
130
131 if (prefix)
132 {
133 /* account for '/' after prefix */
134 size += strlen(prefix) + 1;
135 }
136
137 /* allocate buffer */
138 parsed = malloc(size);
139 ptr = parsed;
140
141 /* malloc failed */
142 if (NULL == ptr)
143 return NULL;
144
145 /* copy prefix */
146 if (prefix)
147 {
148 strcpy(ptr, prefix);
149 ptr += strlen(prefix);
150 *ptr++ = '/';
151 }
152
153 do
154 {
155 if (*path == '\\')
156 *ptr = '/';
157 else
158 *ptr = *path;
159
160 ptr++;
161 } while ('\0' != *(path++));
162
163 return parsed;
164}
165
166/* returns pointer to the rkrs header in rkw file */
167static char *find_section(struct rkw_info_t *rkw_info, enum section_type_t type)
168{
169 char *ptr;
170 struct section_header_t *h;
171
172 switch(type)
173 {
174 case ST_RKRS:
175 case ST_RKST:
176 for (ptr=(char *)rkw_info->rkw; ptr<(char *)rkw_info->rkw+rkw_info->size; ptr++)
177 {
178 h = (struct section_header_t *)ptr;
179 if (h->magic == section_magic[type] &&
180 h->size == sizeof(struct section_header_t) &&
181 h->number_of_named_entries != 0)
182 {
183 fprintf(stderr, "[info]: %s found at 0x%0x\n",
184 section_name[type], (int)(ptr - rkw_info->rkw));
185
186 return ptr;
187 }
188 }
189 break;
190
191 default:
192 fprintf(stderr, "[error]: Not supported section type %d\n", type);
193 return NULL;
194 }
195 return NULL;
196}
197
198/* load rkw file into memory and setup pointers to various sections */
199struct rkw_info_t *rkw_slurp(char *filename)
200{
201 FILE *fp;
202 struct rkw_info_t *rkw_info;
203
204 rkw_info = (struct rkw_info_t *)malloc(sizeof(struct rkw_info_t));
205
206 if (NULL == rkw_info)
207 {
208 fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
209 sizeof(struct rkw_info_t));
210
211 return NULL;
212 }
213
214 fp = fopen(filename, "rb");
215
216 if (NULL == fp)
217 {
218 fprintf(stderr, "[error]: Can't open %s\n", filename);
219 free(rkw_info);
220 return NULL;
221 }
222
223 fseek(fp, 0, SEEK_END);
224 rkw_info->size = ftell(fp);
225 fseek(fp, 0, SEEK_SET);
226
227 rkw_info->rkw = (char *)malloc(rkw_info->size);
228
229 if (NULL == rkw_info->rkw)
230 {
231 fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
232 rkw_info->size);
233
234 free(rkw_info);
235 fclose(fp);
236 return NULL;
237 }
238
239 if (fread(rkw_info->rkw, rkw_info->size, 1, fp) != 1)
240 {
241 fprintf(stderr, "[error]: Can't read %s\n", filename);
242 free(rkw_info);
243 fclose(fp);
244 return NULL;
245 }
246
247 rkw_info->rkrs_info.header = find_section(rkw_info, ST_RKRS);
248 rkw_info->rkrs_info.items = rkw_info->rkrs_info.header +
249 ((struct section_header_t *)
250 (rkw_info->rkrs_info.header))->offset_of_named_entries;
251
252 rkw_info->rkst_info.header = find_section(rkw_info, ST_RKST);
253 rkw_info->rkst_info.items = rkw_info->rkst_info.header +
254 ((struct section_header_t *)
255 (rkw_info->rkst_info.header))->offset_of_named_entries;
256
257 fclose(fp);
258 return rkw_info;
259}
260
261void rkw_free(struct rkw_info_t *rkw_info)
262{
263 free(rkw_info->rkw);
264 free(rkw_info);
265}
266
267static void rkrs_named_item_info(struct rkrs_named_t *item)
268{
269 fprintf(stderr, "[info]: size=0x%0x (%d)\n", item->size, item->size);
270 fprintf(stderr, "[info]: type=0x%0x (%d) %s\n", item->type, item->type, rkrs_action_name[item->type]);
271 fprintf(stderr, "[info]: data_offset=0x%0x (%d)\n", item->data_offset, item->data_offset);
272 fprintf(stderr, "[info]: data_size=0x%0x (%d)\n", item->data_size, item->data_size);
273 fprintf(stderr, "[info]: param[0]=0x%0x (%d)\n", item->param[0], item->param[0]);
274 fprintf(stderr, "[info]: param[1]=0x%0x (%d)\n", item->param[1], item->param[1]);
275 fprintf(stderr, "[info]: param[2]=0x%0x (%d)\n", item->param[2], item->param[2]);
276 fprintf(stderr, "[info]: param[3]=0x%0x (%d)\n", item->param[3], item->param[3]);
277}
278
279static void rkst_named_item_info(struct rkst_named_t *item)
280{
281 fprintf(stderr, "[info]: size=0x%0x (%d)\n", item->size, item->size);
282 fprintf(stderr, "[info]: action=0x%0x (%d) %s\n", item->action, item->action, rkrs_action_name[item->action]);
283 fprintf(stderr, "[info]: data_offset=0x%0x (%d)\n", item->data_offset, item->data_offset);
284 fprintf(stderr, "[info]: data_size=0x%0x (%d)\n", item->data_size, item->data_size);
285 fprintf(stderr, "[info]: name=\"%s\"\n", &item->name);
286}
287
288static struct rkrs_named_t *find_item(struct rkw_info_t *rkw_info, enum rkst_action_t type, bool search_start)
289{
290 static struct rkrs_named_t *item;
291
292 if (search_start)
293 {
294 item = (struct rkrs_named_t *)rkw_info->rkrs_info.items;
295 }
296 else
297 {
298 if (item)
299 item++;
300 else
301 return NULL;
302 }
303
304 while (item->size > 0)
305 {
306 if (item->type == type)
307 {
308 fprintf(stderr, "[info]: Item type=%d found at 0x%x\n", type,
309 (int)((char *)item - rkw_info->rkw));
310 return item;
311 }
312 item++;
313 }
314
315 return NULL;
316}
317
318void rkrs_list_named_items(struct rkw_info_t *rkw_info)
319{
320 struct rkrs_named_t *item = (struct rkrs_named_t *)rkw_info->rkrs_info.items;
321 struct section_header_t *rkrs_header = (struct section_header_t *)(rkw_info->rkrs_info.header);
322 int i;
323
324 for (i=0; i<rkrs_header->number_of_named_entries; i++)
325 {
326 fprintf(stderr, "[info]: rkrs named entry %d\n", i);
327 rkrs_named_item_info(item++);
328 fprintf(stderr, "\n");
329 }
330}
331
332void rkst_list_named_items(struct rkw_info_t *rkw_info)
333{
334 struct rkst_named_t *item = (struct rkst_named_t *)rkw_info->rkst_info.items;
335 struct section_header_t *rkst_header = (struct section_header_t *)(rkw_info->rkst_info.header);
336 int i;
337
338 for (i=0; i<rkst_header->number_of_named_entries; i++)
339 {
340 fprintf(stderr, "[info]: rkst named entry %d\n", i);
341 rkst_named_item_info(item);
342 item = (struct rkst_named_t *)((char *)item + item->size);
343 fprintf(stderr, "\n");
344 }
345}
346
347void unpack_bootloader(struct rkw_info_t *rkw_info, char *prefix)
348{
349 FILE *fp;
350 char *ptr;
351 size_t size;
352 int len;
353 char *buf;
354 struct rkrs_named_t *item = find_item(rkw_info, act_loader, true);
355
356 if (NULL == item)
357 {
358 fprintf(stderr, "[error]: Can't find nand bootloader\n");
359 return;
360 }
361
362 ptr = (char *)(rkw_info->rkrs_info.header) + item->data_offset;
363 size = item->param[0];
364 buf = malloc(size);
365
366 if (NULL == buf)
367 {
368 fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
369 size);
370 return;
371 }
372
373 /* make a copy for decryption */
374 memcpy(buf, ptr, size);
375 encode_page((uint8_t *)buf, (uint8_t *)buf, size);
376 fp = fopen(unixpath("s1.bin", prefix), "w");
377
378 if (NULL == fp)
379 {
380 fprintf(stderr, "[error]: Can't open s1.bin for writing\n");
381 free(buf);
382 return;
383 }
384
385 if (fwrite(buf, size, 1, fp) != 1)
386 {
387 fprintf(stderr, "[error]: Can't write s1.bin file\n");
388 free(buf);
389 fclose(fp);
390 return;
391 }
392
393 fclose(fp);
394
395 ptr = (char *)(rkw_info->rkrs_info.header) + item->param[1];
396 size = item->param[2];
397 len = size;
398 buf = realloc(buf, size);
399
400 if (NULL == buf)
401 {
402 fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
403 size);
404
405 free(buf);
406 return;
407 }
408
409 memcpy(buf, ptr, size);
410 ptr = buf;
411
412 while (len >= 0x200)
413 {
414 encode_page((uint8_t *)ptr, (uint8_t *)ptr, 0x200);
415 ptr += 0x200;
416 len -= 0x200;
417 }
418 encode_page((uint8_t *)ptr, (uint8_t *)ptr, len);
419
420 fp = fopen(unixpath("s2.bin", prefix), "w");
421
422 if (NULL == fp)
423 {
424 fprintf(stderr, "[error]: Can't open s2.bin for writing\n");
425 free(buf);
426 return;
427 }
428
429 if (fwrite(buf, size, 1, fp) != 1)
430 {
431 fprintf(stderr, "[error]: Can't write s2.bin file\n");
432 free(buf);
433 fclose(fp);
434 return;
435 }
436
437 fclose(fp);
438 free(buf);
439 fprintf(stderr, "[info]: Extracted bootloader version: %x.%x\n",
440 (item->param[3] >> 8) & 0xff, item->param[3] & 0xff);
441}
442
443void unpack_addfile(struct rkw_info_t *rkw_info, char *prefix)
444{
445 FILE *fp;
446 char *name;
447 int name_len;
448
449 struct rkrs_named_t *item = find_item(rkw_info, act_addfile, true);
450
451 do
452 {
453 name = unixpath(rkw_info->rkrs_info.header + item->data_offset, prefix);
454 name_len = item->param[0];
455
456 fprintf(stderr, "[info]: unpacking addfile %s\n", name);
457
458 fp = fopen(name, "w");
459
460 if (NULL == fp)
461 {
462 fprintf(stderr, "[error]: Can't open %s for writing\n", name);
463 return;
464 }
465
466 if (fwrite(rkw_info->rkrs_info.header + item->data_offset + name_len,
467 item->data_size - name_len, 1, fp) != 1)
468 {
469 fprintf(stderr, "[error]: Can't write %s file\n", name);
470 fclose(fp);
471 return;
472 }
473
474 fclose(fp);
475 } while (NULL != (item = find_item(rkw_info, act_addfile, false)));
476}
477
478/* unpack content of RKST section
479 * this mimics what is done when processing 'fsoper' field of RKRS
480 */
481void unpack_rkst(struct rkw_info_t *rkw_info, char *prefix)
482{
483 FILE *fp;
484 struct rkst_named_t *item = (struct rkst_named_t *)rkw_info->rkst_info.items;
485 struct section_header_t *rkst_header = (struct section_header_t *)(rkw_info->rkst_info.header);
486 char *name;
487 int i;
488
489 if (prefix)
490 {
491 if (0 != mkdir(prefix, 0755))
492 {
493 fprintf(stderr, "[error]: Can't create %s directory (%s)\n",
494 prefix, strerror(errno));
495 return;
496 }
497 }
498
499 fprintf(stderr, "[info]: Unpacking content of RKST section\n");
500
501 for (i=0; i<rkst_header->number_of_named_entries; i++)
502 {
503 name = unixpath((char *)&(item->name), prefix);
504
505 switch (item->action)
506 {
507 case act_mkdir:
508 if (0 != mkdir(name, 0755))
509 {
510 fprintf(stderr, "[error]: Can't create %s directory (%s)\n",
511 name, strerror(errno));
512 return;
513 }
514 fprintf(stderr, "[info]: mkdir %s\n", name);
515 break;
516
517 case act_fcopy:
518 fp = fopen(name, "w");
519 if (NULL == fp)
520 {
521 fprintf(stderr, "[error]: Can't open %s for writing (%s)\n",
522 name, strerror(errno));
523 return;
524 }
525
526 fwrite((char *)rkst_header + item->data_offset, item->data_size, 1, fp);
527 fprintf(stderr, "[info]: unpack %s\n", name);
528 fclose(fp);
529 break;
530
531 default:
532 break;
533 }
534
535 if (name) free(name);
536 item = (struct rkst_named_t *)((char *)item + item->size);
537 }
538}
diff --git a/utils/rk27utils/rkwtool/rkw.h b/utils/rk27utils/rkwtool/rkw.h
new file mode 100644
index 0000000000..eba673c974
--- /dev/null
+++ b/utils/rk27utils/rkwtool/rkw.h
@@ -0,0 +1,123 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2014 by 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 <stdint.h>
22
23#define RKLD_MAGIC 0x4C44524B
24#define RKRS_MAGIC 0x53524B52
25#define RKST_MAGIC 0X53544B52
26
27enum section_type_t {
28 ST_RKLD,
29 ST_RKRS,
30 ST_RKST
31};
32
33enum rkst_action_t {
34 act_null = 0,
35 act_mkdir = 1,
36 act_fcopy = 2,
37 act_fsoper = 3,
38 act_format = 4,
39 act_loader = 5,
40
41 act_dispbmp = 10,
42 act_dispstr = 11,
43 act_setfont = 12,
44
45 act_delay = 20,
46
47 act_system = 100,
48 act_uilogo = 100,
49 act_readme = 101,
50 act_copyright = 102,
51 act_select = 103,
52 act_restart = 104,
53
54 act_regkey = 120,
55 act_version = 121,
56
57 act_freplace = 130,
58 act_fpreplace = 131,
59 act_fsdel = 132,
60
61 act_space = 200,
62
63 act_addfile = 300,
64
65 act_setmem = 1000,
66 act_getmem = 1001,
67};
68
69struct section_header_t {
70 uint32_t size;
71 uint32_t magic;
72 uint32_t property;
73 uint32_t timestamp;
74 uint32_t allign;
75 uint32_t file_size;
76 uint16_t size_of_name_dir;
77 uint16_t size_of_id_dir;
78 uint16_t number_of_named_entries;
79 uint16_t number_of_id_entries;
80 uint32_t offset_of_named_entries;
81 uint32_t offset_of_id_entries;
82} __attribute__((__packed__));
83
84struct rkrs_named_t {
85 uint32_t size;
86 uint32_t type;
87 uint32_t data_offset;
88 uint32_t data_size;
89 uint32_t param[4];
90} __attribute__((__packed__));
91
92struct rkst_named_t {
93 uint32_t size;
94 uint32_t action;
95 uint32_t data_offset;
96 uint32_t data_size;
97 uint8_t name;
98};
99
100struct section_info_t {
101 char *header;
102 char *items;
103};
104
105struct rkw_info_t {
106 char *rkw;
107 long size;
108 struct section_info_t rkrs_info;
109 struct section_info_t rkst_info;
110};
111
112/* general functions */
113struct rkw_info_t *rkw_slurp(char *filename);
114void rkw_free(struct rkw_info_t *rkw_info);
115
116/* info functions */
117void rkrs_list_named_items(struct rkw_info_t *rkw_info);
118void rkst_list_named_items(struct rkw_info_t *rkw_info);
119
120/* extract functions */
121void unpack_bootloader(struct rkw_info_t *rkw_info, char *prefix);
122void unpack_rkst(struct rkw_info_t *rkw_info, char *prefix);
123void unpack_addfile(struct rkw_info_t *rkw_info, char *prefix);