mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 10:07:38 -04:00
rkwtool: The tool to inspect and extract update RKW files
Change-Id: Ie32d0a597b93d23a7d5946a3d9409572b41b45bc
This commit is contained in:
parent
81ffd9bfee
commit
53d9f2e6a7
5 changed files with 812 additions and 0 deletions
|
@ -36,6 +36,21 @@ rockchip player.
|
|||
|
||||
You need libusb-1.0 + header files in order to compile this utility.
|
||||
|
||||
|
||||
rkwtool
|
||||
This directory contains tool to inspect and extract content of
|
||||
'full' update RKW file.
|
||||
|
||||
The RKW file contains specific section which instruct update
|
||||
routine of the DAP what to do, custom archive with firmware files,
|
||||
images of stage1 and stage2 nand bootloader and Rock27Boot.bin file
|
||||
image. Nand bootloader images are stored in scrambled form but
|
||||
the tool deciphers it to plain binary during extraction.
|
||||
|
||||
More complete descritpion of file format can be found on wiki:
|
||||
http://www.rockbox.org/wiki/RKWFileFormat
|
||||
|
||||
|
||||
nandextract
|
||||
This directory contains quick and dirty tool which allows to extract
|
||||
nand bootloader from raw dump of the first nand block. The main reason
|
||||
|
|
7
utils/rk27utils/rkwtool/Makefile
Normal file
7
utils/rk27utils/rkwtool/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
all: rkwtool
|
||||
|
||||
rkwtool: rkw.c main.c
|
||||
gcc -g -std=c99 -o $@ -W -Wall $^
|
||||
|
||||
clean:
|
||||
rm -fr rkwtool
|
129
utils/rk27utils/rkwtool/main.c
Normal file
129
utils/rk27utils/rkwtool/main.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2014 by Marcin Bukat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "rkw.h"
|
||||
|
||||
#define VERSION "v0.1"
|
||||
|
||||
static void banner(void)
|
||||
{
|
||||
printf("RKWtool " VERSION " (C) Marcin Bukat 2014\n");
|
||||
printf("This is free software; see the source for copying conditions. There is NO\n");
|
||||
printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
|
||||
}
|
||||
|
||||
static void usage(char *name)
|
||||
{
|
||||
banner();
|
||||
|
||||
printf("Usage: %s [-i] [-b] [-e] [-a] [-o prefix] file.rkw\n", name);
|
||||
printf("-i\t\tprint info about RKW file\n");
|
||||
printf("-b\t\textract nand bootloader images (s1.bin and s2.bin)\n");
|
||||
printf("-e\t\textract firmware files stored in RKST section\n");
|
||||
printf("-o prefix\twhen extracting firmware files put it there\n");
|
||||
printf("-a\t\textract additional file(s) (usually Rock27Boot.bin)\n");
|
||||
printf("-A\t\textract all data\n");
|
||||
printf("file.rkw\tRKW file to be processed\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
struct rkw_info_t *rkw_info = NULL;
|
||||
char *prefix = NULL;
|
||||
bool info = false;
|
||||
bool extract = false;
|
||||
bool bootloader = false;
|
||||
bool addfile = false;
|
||||
|
||||
while ((opt = getopt(argc, argv, "iebo:aA")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'i':
|
||||
info = true;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
extract = true;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
bootloader = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
prefix = optarg;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
addfile = true;
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
extract = true;
|
||||
bootloader = true;
|
||||
addfile = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind) != 1 ||
|
||||
(!info && !extract && ! bootloader && !addfile))
|
||||
{
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
banner();
|
||||
|
||||
rkw_info = rkw_slurp(argv[optind]);
|
||||
|
||||
if (rkw_info)
|
||||
{
|
||||
if (info)
|
||||
{
|
||||
rkrs_list_named_items(rkw_info);
|
||||
rkst_list_named_items(rkw_info);
|
||||
}
|
||||
|
||||
if (extract)
|
||||
unpack_rkst(rkw_info, prefix);
|
||||
|
||||
if (bootloader)
|
||||
unpack_bootloader(rkw_info, prefix);
|
||||
|
||||
if (addfile)
|
||||
unpack_addfile(rkw_info, prefix);
|
||||
|
||||
rkw_free(rkw_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
538
utils/rk27utils/rkwtool/rkw.c
Normal file
538
utils/rk27utils/rkwtool/rkw.c
Normal file
|
@ -0,0 +1,538 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2014 by Marcin Bukat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "rkw.h"
|
||||
|
||||
const char *section_name[] = {
|
||||
"RKLD",
|
||||
"RKRS",
|
||||
"RKST"
|
||||
};
|
||||
|
||||
const uint32_t section_magic[] = {
|
||||
RKLD_MAGIC,
|
||||
RKRS_MAGIC,
|
||||
RKST_MAGIC
|
||||
};
|
||||
|
||||
const char *rkrs_action_name[] = {
|
||||
[act_null] = "null",
|
||||
[act_mkdir] = "mkdir",
|
||||
[act_fcopy] = "fcopy",
|
||||
[act_fsoper] = "fsoper",
|
||||
[act_format] = "format",
|
||||
[act_loader] = "loader",
|
||||
[act_dispbmp] = "dispbmp",
|
||||
[act_dispstr] = "dispstr",
|
||||
[act_setfont] = "setfont",
|
||||
[act_delay] = "delay",
|
||||
[act_system] = "system",
|
||||
[act_readme] = "readme",
|
||||
[act_copyright] = "copyright",
|
||||
[act_select] = "select",
|
||||
[act_restart] = "restart",
|
||||
[act_regkey] = "regkey",
|
||||
[act_version] = "version",
|
||||
[act_freplace] = "freplace",
|
||||
[act_fpreplace] = "fpreplace",
|
||||
[act_fsdel] = "fsdel",
|
||||
[act_space] = "space",
|
||||
[act_addfile] = "addfile",
|
||||
[act_setmem] = "setmem",
|
||||
[act_getmem] = "getmem"
|
||||
};
|
||||
|
||||
/* scrambling/descrambling reverse engineered by AleMaxx */
|
||||
static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
|
||||
{
|
||||
|
||||
uint8_t key[] = {
|
||||
0x7C, 0x4E, 0x03, 0x04,
|
||||
0x55, 0x05, 0x09, 0x07,
|
||||
0x2D, 0x2C, 0x7B, 0x38,
|
||||
0x17, 0x0D, 0x17, 0x11
|
||||
};
|
||||
int i, i3, x, val, idx;
|
||||
|
||||
uint8_t key1[0x100];
|
||||
uint8_t key2[0x100];
|
||||
|
||||
for (i=0; i<0x100; i++) {
|
||||
key1[i] = i;
|
||||
key2[i] = key[i&0xf];
|
||||
}
|
||||
|
||||
i3 = 0;
|
||||
for (i=0; i<0x100; i++) {
|
||||
x = key1[i];
|
||||
i3 = key1[i] + i3;
|
||||
i3 += key2[i];
|
||||
i3 &= 0xff;
|
||||
key1[i] = key1[i3];
|
||||
key1[i3] = x;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
for (i=0; i<size; i++) {
|
||||
x = key1[(i+1) & 0xff];
|
||||
val = x;
|
||||
idx = (x + idx) & 0xff;
|
||||
key1[(i+1) & 0xff] = key1[idx];
|
||||
key1[idx] = (x & 0xff);
|
||||
val = (key1[(i+1)&0xff] + x) & 0xff;
|
||||
val = key1[val];
|
||||
outpg[i] = val ^ inpg[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* take path as stored in RKST and convert it to unix path
|
||||
* with optional prefix
|
||||
*/
|
||||
static char *unixpath(char *path, char *prefix)
|
||||
{
|
||||
char *parsed, *ptr;
|
||||
size_t size = 0;
|
||||
|
||||
if (NULL == path)
|
||||
return NULL;
|
||||
|
||||
size = strlen(path) + 1;
|
||||
|
||||
/* full windows path i.e C:\something */
|
||||
if (strlen(path) > 2 && ':' == path[1])
|
||||
path += 3;
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
/* account for '/' after prefix */
|
||||
size += strlen(prefix) + 1;
|
||||
}
|
||||
|
||||
/* allocate buffer */
|
||||
parsed = malloc(size);
|
||||
ptr = parsed;
|
||||
|
||||
/* malloc failed */
|
||||
if (NULL == ptr)
|
||||
return NULL;
|
||||
|
||||
/* copy prefix */
|
||||
if (prefix)
|
||||
{
|
||||
strcpy(ptr, prefix);
|
||||
ptr += strlen(prefix);
|
||||
*ptr++ = '/';
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (*path == '\\')
|
||||
*ptr = '/';
|
||||
else
|
||||
*ptr = *path;
|
||||
|
||||
ptr++;
|
||||
} while ('\0' != *(path++));
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/* returns pointer to the rkrs header in rkw file */
|
||||
static char *find_section(struct rkw_info_t *rkw_info, enum section_type_t type)
|
||||
{
|
||||
char *ptr;
|
||||
struct section_header_t *h;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case ST_RKRS:
|
||||
case ST_RKST:
|
||||
for (ptr=(char *)rkw_info->rkw; ptr<(char *)rkw_info->rkw+rkw_info->size; ptr++)
|
||||
{
|
||||
h = (struct section_header_t *)ptr;
|
||||
if (h->magic == section_magic[type] &&
|
||||
h->size == sizeof(struct section_header_t) &&
|
||||
h->number_of_named_entries != 0)
|
||||
{
|
||||
fprintf(stderr, "[info]: %s found at 0x%0x\n",
|
||||
section_name[type], (int)(ptr - rkw_info->rkw));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "[error]: Not supported section type %d\n", type);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* load rkw file into memory and setup pointers to various sections */
|
||||
struct rkw_info_t *rkw_slurp(char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
struct rkw_info_t *rkw_info;
|
||||
|
||||
rkw_info = (struct rkw_info_t *)malloc(sizeof(struct rkw_info_t));
|
||||
|
||||
if (NULL == rkw_info)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
|
||||
sizeof(struct rkw_info_t));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't open %s\n", filename);
|
||||
free(rkw_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
rkw_info->size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
rkw_info->rkw = (char *)malloc(rkw_info->size);
|
||||
|
||||
if (NULL == rkw_info->rkw)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
|
||||
rkw_info->size);
|
||||
|
||||
free(rkw_info);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fread(rkw_info->rkw, rkw_info->size, 1, fp) != 1)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't read %s\n", filename);
|
||||
free(rkw_info);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rkw_info->rkrs_info.header = find_section(rkw_info, ST_RKRS);
|
||||
rkw_info->rkrs_info.items = rkw_info->rkrs_info.header +
|
||||
((struct section_header_t *)
|
||||
(rkw_info->rkrs_info.header))->offset_of_named_entries;
|
||||
|
||||
rkw_info->rkst_info.header = find_section(rkw_info, ST_RKST);
|
||||
rkw_info->rkst_info.items = rkw_info->rkst_info.header +
|
||||
((struct section_header_t *)
|
||||
(rkw_info->rkst_info.header))->offset_of_named_entries;
|
||||
|
||||
fclose(fp);
|
||||
return rkw_info;
|
||||
}
|
||||
|
||||
void rkw_free(struct rkw_info_t *rkw_info)
|
||||
{
|
||||
free(rkw_info->rkw);
|
||||
free(rkw_info);
|
||||
}
|
||||
|
||||
static void rkrs_named_item_info(struct rkrs_named_t *item)
|
||||
{
|
||||
fprintf(stderr, "[info]: size=0x%0x (%d)\n", item->size, item->size);
|
||||
fprintf(stderr, "[info]: type=0x%0x (%d) %s\n", item->type, item->type, rkrs_action_name[item->type]);
|
||||
fprintf(stderr, "[info]: data_offset=0x%0x (%d)\n", item->data_offset, item->data_offset);
|
||||
fprintf(stderr, "[info]: data_size=0x%0x (%d)\n", item->data_size, item->data_size);
|
||||
fprintf(stderr, "[info]: param[0]=0x%0x (%d)\n", item->param[0], item->param[0]);
|
||||
fprintf(stderr, "[info]: param[1]=0x%0x (%d)\n", item->param[1], item->param[1]);
|
||||
fprintf(stderr, "[info]: param[2]=0x%0x (%d)\n", item->param[2], item->param[2]);
|
||||
fprintf(stderr, "[info]: param[3]=0x%0x (%d)\n", item->param[3], item->param[3]);
|
||||
}
|
||||
|
||||
static void rkst_named_item_info(struct rkst_named_t *item)
|
||||
{
|
||||
fprintf(stderr, "[info]: size=0x%0x (%d)\n", item->size, item->size);
|
||||
fprintf(stderr, "[info]: action=0x%0x (%d) %s\n", item->action, item->action, rkrs_action_name[item->action]);
|
||||
fprintf(stderr, "[info]: data_offset=0x%0x (%d)\n", item->data_offset, item->data_offset);
|
||||
fprintf(stderr, "[info]: data_size=0x%0x (%d)\n", item->data_size, item->data_size);
|
||||
fprintf(stderr, "[info]: name=\"%s\"\n", &item->name);
|
||||
}
|
||||
|
||||
static struct rkrs_named_t *find_item(struct rkw_info_t *rkw_info, enum rkst_action_t type, bool search_start)
|
||||
{
|
||||
static struct rkrs_named_t *item;
|
||||
|
||||
if (search_start)
|
||||
{
|
||||
item = (struct rkrs_named_t *)rkw_info->rkrs_info.items;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item)
|
||||
item++;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (item->size > 0)
|
||||
{
|
||||
if (item->type == type)
|
||||
{
|
||||
fprintf(stderr, "[info]: Item type=%d found at 0x%x\n", type,
|
||||
(int)((char *)item - rkw_info->rkw));
|
||||
return item;
|
||||
}
|
||||
item++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rkrs_list_named_items(struct rkw_info_t *rkw_info)
|
||||
{
|
||||
struct rkrs_named_t *item = (struct rkrs_named_t *)rkw_info->rkrs_info.items;
|
||||
struct section_header_t *rkrs_header = (struct section_header_t *)(rkw_info->rkrs_info.header);
|
||||
int i;
|
||||
|
||||
for (i=0; i<rkrs_header->number_of_named_entries; i++)
|
||||
{
|
||||
fprintf(stderr, "[info]: rkrs named entry %d\n", i);
|
||||
rkrs_named_item_info(item++);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void rkst_list_named_items(struct rkw_info_t *rkw_info)
|
||||
{
|
||||
struct rkst_named_t *item = (struct rkst_named_t *)rkw_info->rkst_info.items;
|
||||
struct section_header_t *rkst_header = (struct section_header_t *)(rkw_info->rkst_info.header);
|
||||
int i;
|
||||
|
||||
for (i=0; i<rkst_header->number_of_named_entries; i++)
|
||||
{
|
||||
fprintf(stderr, "[info]: rkst named entry %d\n", i);
|
||||
rkst_named_item_info(item);
|
||||
item = (struct rkst_named_t *)((char *)item + item->size);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void unpack_bootloader(struct rkw_info_t *rkw_info, char *prefix)
|
||||
{
|
||||
FILE *fp;
|
||||
char *ptr;
|
||||
size_t size;
|
||||
int len;
|
||||
char *buf;
|
||||
struct rkrs_named_t *item = find_item(rkw_info, act_loader, true);
|
||||
|
||||
if (NULL == item)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't find nand bootloader\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = (char *)(rkw_info->rkrs_info.header) + item->data_offset;
|
||||
size = item->param[0];
|
||||
buf = malloc(size);
|
||||
|
||||
if (NULL == buf)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
|
||||
size);
|
||||
return;
|
||||
}
|
||||
|
||||
/* make a copy for decryption */
|
||||
memcpy(buf, ptr, size);
|
||||
encode_page((uint8_t *)buf, (uint8_t *)buf, size);
|
||||
fp = fopen(unixpath("s1.bin", prefix), "w");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't open s1.bin for writing\n");
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite(buf, size, 1, fp) != 1)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't write s1.bin file\n");
|
||||
free(buf);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
ptr = (char *)(rkw_info->rkrs_info.header) + item->param[1];
|
||||
size = item->param[2];
|
||||
len = size;
|
||||
buf = realloc(buf, size);
|
||||
|
||||
if (NULL == buf)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't allocate %ld bytes of memory\n",
|
||||
size);
|
||||
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(buf, ptr, size);
|
||||
ptr = buf;
|
||||
|
||||
while (len >= 0x200)
|
||||
{
|
||||
encode_page((uint8_t *)ptr, (uint8_t *)ptr, 0x200);
|
||||
ptr += 0x200;
|
||||
len -= 0x200;
|
||||
}
|
||||
encode_page((uint8_t *)ptr, (uint8_t *)ptr, len);
|
||||
|
||||
fp = fopen(unixpath("s2.bin", prefix), "w");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't open s2.bin for writing\n");
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite(buf, size, 1, fp) != 1)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't write s2.bin file\n");
|
||||
free(buf);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
free(buf);
|
||||
fprintf(stderr, "[info]: Extracted bootloader version: %x.%x\n",
|
||||
(item->param[3] >> 8) & 0xff, item->param[3] & 0xff);
|
||||
}
|
||||
|
||||
void unpack_addfile(struct rkw_info_t *rkw_info, char *prefix)
|
||||
{
|
||||
FILE *fp;
|
||||
char *name;
|
||||
int name_len;
|
||||
|
||||
struct rkrs_named_t *item = find_item(rkw_info, act_addfile, true);
|
||||
|
||||
do
|
||||
{
|
||||
name = unixpath(rkw_info->rkrs_info.header + item->data_offset, prefix);
|
||||
name_len = item->param[0];
|
||||
|
||||
fprintf(stderr, "[info]: unpacking addfile %s\n", name);
|
||||
|
||||
fp = fopen(name, "w");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't open %s for writing\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite(rkw_info->rkrs_info.header + item->data_offset + name_len,
|
||||
item->data_size - name_len, 1, fp) != 1)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't write %s file\n", name);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
} while (NULL != (item = find_item(rkw_info, act_addfile, false)));
|
||||
}
|
||||
|
||||
/* unpack content of RKST section
|
||||
* this mimics what is done when processing 'fsoper' field of RKRS
|
||||
*/
|
||||
void unpack_rkst(struct rkw_info_t *rkw_info, char *prefix)
|
||||
{
|
||||
FILE *fp;
|
||||
struct rkst_named_t *item = (struct rkst_named_t *)rkw_info->rkst_info.items;
|
||||
struct section_header_t *rkst_header = (struct section_header_t *)(rkw_info->rkst_info.header);
|
||||
char *name;
|
||||
int i;
|
||||
|
||||
if (prefix)
|
||||
{
|
||||
if (0 != mkdir(prefix, 0755))
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't create %s directory (%s)\n",
|
||||
prefix, strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "[info]: Unpacking content of RKST section\n");
|
||||
|
||||
for (i=0; i<rkst_header->number_of_named_entries; i++)
|
||||
{
|
||||
name = unixpath((char *)&(item->name), prefix);
|
||||
|
||||
switch (item->action)
|
||||
{
|
||||
case act_mkdir:
|
||||
if (0 != mkdir(name, 0755))
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't create %s directory (%s)\n",
|
||||
name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "[info]: mkdir %s\n", name);
|
||||
break;
|
||||
|
||||
case act_fcopy:
|
||||
fp = fopen(name, "w");
|
||||
if (NULL == fp)
|
||||
{
|
||||
fprintf(stderr, "[error]: Can't open %s for writing (%s)\n",
|
||||
name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite((char *)rkst_header + item->data_offset, item->data_size, 1, fp);
|
||||
fprintf(stderr, "[info]: unpack %s\n", name);
|
||||
fclose(fp);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (name) free(name);
|
||||
item = (struct rkst_named_t *)((char *)item + item->size);
|
||||
}
|
||||
}
|
123
utils/rk27utils/rkwtool/rkw.h
Normal file
123
utils/rk27utils/rkwtool/rkw.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
*
|
||||
* Copyright (C) 2014 by Marcin Bukat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define RKLD_MAGIC 0x4C44524B
|
||||
#define RKRS_MAGIC 0x53524B52
|
||||
#define RKST_MAGIC 0X53544B52
|
||||
|
||||
enum section_type_t {
|
||||
ST_RKLD,
|
||||
ST_RKRS,
|
||||
ST_RKST
|
||||
};
|
||||
|
||||
enum rkst_action_t {
|
||||
act_null = 0,
|
||||
act_mkdir = 1,
|
||||
act_fcopy = 2,
|
||||
act_fsoper = 3,
|
||||
act_format = 4,
|
||||
act_loader = 5,
|
||||
|
||||
act_dispbmp = 10,
|
||||
act_dispstr = 11,
|
||||
act_setfont = 12,
|
||||
|
||||
act_delay = 20,
|
||||
|
||||
act_system = 100,
|
||||
act_uilogo = 100,
|
||||
act_readme = 101,
|
||||
act_copyright = 102,
|
||||
act_select = 103,
|
||||
act_restart = 104,
|
||||
|
||||
act_regkey = 120,
|
||||
act_version = 121,
|
||||
|
||||
act_freplace = 130,
|
||||
act_fpreplace = 131,
|
||||
act_fsdel = 132,
|
||||
|
||||
act_space = 200,
|
||||
|
||||
act_addfile = 300,
|
||||
|
||||
act_setmem = 1000,
|
||||
act_getmem = 1001,
|
||||
};
|
||||
|
||||
struct section_header_t {
|
||||
uint32_t size;
|
||||
uint32_t magic;
|
||||
uint32_t property;
|
||||
uint32_t timestamp;
|
||||
uint32_t allign;
|
||||
uint32_t file_size;
|
||||
uint16_t size_of_name_dir;
|
||||
uint16_t size_of_id_dir;
|
||||
uint16_t number_of_named_entries;
|
||||
uint16_t number_of_id_entries;
|
||||
uint32_t offset_of_named_entries;
|
||||
uint32_t offset_of_id_entries;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct rkrs_named_t {
|
||||
uint32_t size;
|
||||
uint32_t type;
|
||||
uint32_t data_offset;
|
||||
uint32_t data_size;
|
||||
uint32_t param[4];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct rkst_named_t {
|
||||
uint32_t size;
|
||||
uint32_t action;
|
||||
uint32_t data_offset;
|
||||
uint32_t data_size;
|
||||
uint8_t name;
|
||||
};
|
||||
|
||||
struct section_info_t {
|
||||
char *header;
|
||||
char *items;
|
||||
};
|
||||
|
||||
struct rkw_info_t {
|
||||
char *rkw;
|
||||
long size;
|
||||
struct section_info_t rkrs_info;
|
||||
struct section_info_t rkst_info;
|
||||
};
|
||||
|
||||
/* general functions */
|
||||
struct rkw_info_t *rkw_slurp(char *filename);
|
||||
void rkw_free(struct rkw_info_t *rkw_info);
|
||||
|
||||
/* info functions */
|
||||
void rkrs_list_named_items(struct rkw_info_t *rkw_info);
|
||||
void rkst_list_named_items(struct rkw_info_t *rkw_info);
|
||||
|
||||
/* extract functions */
|
||||
void unpack_bootloader(struct rkw_info_t *rkw_info, char *prefix);
|
||||
void unpack_rkst(struct rkw_info_t *rkw_info, char *prefix);
|
||||
void unpack_addfile(struct rkw_info_t *rkw_info, char *prefix);
|
Loading…
Add table
Add a link
Reference in a new issue