A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd

rkwtool: The tool to inspect and extract update RKW files

Change-Id: Ie32d0a597b93d23a7d5946a3d9409572b41b45bc

+812
+15
utils/rk27utils/README
··· 36 36 37 37 You need libusb-1.0 + header files in order to compile this utility. 38 38 39 + 40 + rkwtool 41 + This directory contains tool to inspect and extract content of 42 + 'full' update RKW file. 43 + 44 + The RKW file contains specific section which instruct update 45 + routine of the DAP what to do, custom archive with firmware files, 46 + images of stage1 and stage2 nand bootloader and Rock27Boot.bin file 47 + image. Nand bootloader images are stored in scrambled form but 48 + the tool deciphers it to plain binary during extraction. 49 + 50 + More complete descritpion of file format can be found on wiki: 51 + http://www.rockbox.org/wiki/RKWFileFormat 52 + 53 + 39 54 nandextract 40 55 This directory contains quick and dirty tool which allows to extract 41 56 nand bootloader from raw dump of the first nand block. The main reason
+7
utils/rk27utils/rkwtool/Makefile
··· 1 + all: rkwtool 2 + 3 + rkwtool: rkw.c main.c 4 + gcc -g -std=c99 -o $@ -W -Wall $^ 5 + 6 + clean: 7 + rm -fr rkwtool
+129
utils/rk27utils/rkwtool/main.c
··· 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 + 29 + static 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 + 36 + static 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 + 50 + int 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 + }
+538
utils/rk27utils/rkwtool/rkw.c
··· 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 + 32 + const char *section_name[] = { 33 + "RKLD", 34 + "RKRS", 35 + "RKST" 36 + }; 37 + 38 + const uint32_t section_magic[] = { 39 + RKLD_MAGIC, 40 + RKRS_MAGIC, 41 + RKST_MAGIC 42 + }; 43 + 44 + const 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 */ 72 + static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size) 73 + { 74 + 75 + uint8_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 + */ 117 + static 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 */ 167 + static 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 */ 199 + struct 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 + 261 + void rkw_free(struct rkw_info_t *rkw_info) 262 + { 263 + free(rkw_info->rkw); 264 + free(rkw_info); 265 + } 266 + 267 + static 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 + 279 + static 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 + 288 + static 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 + 318 + void 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 + 332 + void 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 + 347 + void 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 + 443 + void 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 + */ 481 + void 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 + }
+123
utils/rk27utils/rkwtool/rkw.h
··· 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 + 27 + enum section_type_t { 28 + ST_RKLD, 29 + ST_RKRS, 30 + ST_RKST 31 + }; 32 + 33 + enum 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 + 69 + struct 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 + 84 + struct 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 + 92 + struct 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 + 100 + struct section_info_t { 101 + char *header; 102 + char *items; 103 + }; 104 + 105 + struct 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 */ 113 + struct rkw_info_t *rkw_slurp(char *filename); 114 + void rkw_free(struct rkw_info_t *rkw_info); 115 + 116 + /* info functions */ 117 + void rkrs_list_named_items(struct rkw_info_t *rkw_info); 118 + void rkst_list_named_items(struct rkw_info_t *rkw_info); 119 + 120 + /* extract functions */ 121 + void unpack_bootloader(struct rkw_info_t *rkw_info, char *prefix); 122 + void unpack_rkst(struct rkw_info_t *rkw_info, char *prefix); 123 + void unpack_addfile(struct rkw_info_t *rkw_info, char *prefix);