Add RKW firmware file format loader

Change-Id: I5283fdcdb8d263fd9375a6d29396f82650aeb686
This commit is contained in:
Marcin Bukat 2012-03-02 16:29:42 +01:00
parent f35e300304
commit 2f8b44aae2
5 changed files with 337 additions and 0 deletions

View File

@ -137,6 +137,9 @@ common/crc32.c
#ifdef MI4_FORMAT
common/crc32-mi4.c
#endif
#ifdef RKW_FORMAT
common/crc32-rkw.c
#endif
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
common/dir_uncached.c
common/file.c
@ -1473,6 +1476,7 @@ target/arm/rk27xx/ftl-rk27xx.c
target/arm/rk27xx/nand-rk27xx.c
target/arm/rk27xx/usb-rk27xx.c
target/arm/rk27xx/lcdif-rk27xx.c
target/arm/rk27xx/rkw-loader.c
#ifndef BOOTLOADER
target/arm/rk27xx/pcm-rk27xx.c
target/arm/rk27xx/debug-rk27xx.c

111
firmware/common/crc32-rkw.c Normal file
View File

@ -0,0 +1,111 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2012 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 "crc32-rkw.h"
/* Slightly modified version of the crc32 algorithm generated with help of
* pycrc http://www.tty1.net/pycrc/index_en.html
* pycrc.py --width 32 --xor-in 0 --xor-out 0 --poly 0x04c10db7 \
* --reflect-in false --reflect-out false \
* --algorithm table-driven --table-idx-width 8 --generate c
*/
static const uint32_t crc_table[256] = {
0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9,
0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005,
0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61,
0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd,
0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9,
0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75,
0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011,
0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd,
0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039,
0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5,
0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81,
0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d,
0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49,
0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95,
0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1,
0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d,
0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae,
0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072,
0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16,
0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca,
0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde,
0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02,
0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066,
0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba,
0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e,
0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692,
0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6,
0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a,
0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e,
0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2,
0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686,
0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a,
0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637,
0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb,
0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f,
0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53,
0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47,
0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b,
0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff,
0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623,
0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7,
0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b,
0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f,
0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3,
0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7,
0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b,
0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f,
0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3,
0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640,
0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c,
0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8,
0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24,
0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30,
0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec,
0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088,
0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654,
0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0,
0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c,
0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18,
0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4,
0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0,
0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c,
0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668,
0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4
};
uint32_t crc32_rkw(const uint8_t *data, uint32_t len)
{
uint8_t tbl_idx;
uint32_t crc = 0;
while (len--)
{
tbl_idx = ((crc >> 24) ^ *data) & 0xff;
crc = (crc_table[tbl_idx] ^ (crc << 8)) & 0xffffffff;
data++;
}
return crc;
}

46
firmware/export/rkw.h Normal file
View File

@ -0,0 +1,46 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2012 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 1
* 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 RKW_HEADER_CRC 0x40000000
#define RKW_IMAGE_CRC 0x20000000
struct rkw_header_t {
uint32_t magic_number; /* Magic number. 0x4C44524B */
uint32_t header_size; /* Size of the header */
uint32_t image_base; /* Base address of the firmware image */
uint32_t load_address; /* Load address */
uint32_t load_limit; /* End of the firmware image */
uint32_t bss_start; /* This is the start of .bss section of the firmware I suppose */
uint32_t reserved0; /* reserved - I've seen only zeros in this field so far */
uint32_t reserved1; /* reserved - I've seen only zeros in this field so far */
uint32_t entry_point; /* Entry point address */
uint32_t load_options; /* 0x80000000 - setup flag (I don't know what it means
* but is present in every RKW I saw),
* 0x40000000 - check header crc,
* 0x20000000 - check firmware crc
*/
uint32_t crc; /* crc32 of the header (excluding crc32 field itself) */
};
const char *rkw_strerror(int8_t errno);
int load_rkw(unsigned char* buf, const char* filename, int buffer_size);

View File

@ -0,0 +1,27 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2012 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>
#ifndef _CRC32_RKW_H
#define _CRC32_RKW_H
uint32_t crc32_rkw (const uint8_t *src, uint32_t length);
#endif

View File

@ -0,0 +1,149 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
*
* Copyright (C) 2012 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 1
* 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 "config.h"
#include "rkw.h"
#include "crc32-rkw.h"
#include "file.h"
#include "panic.h"
/* error strings sorted by number */
/* error 0 is empty */
static const char *err_str[] = {
"Loading OK",
"Can't open RKW file",
"Can't read RKW header",
"Invalid RKW magic number",
"RKW header CRC error",
"RKW file too big",
"RKW Load address mismatch",
"Bad model number",
"Error Reading File",
"RKW firmware CRC error"
};
const char *rkw_strerror(int8_t errno)
{
if (-errno >= sizeof(err_str)/sizeof(err_str[0]) || errno > 0)
return "Unknown error";
return err_str[-errno];
}
/* loosely based on load_firmware()
* on success we return size loaded image
* on error we return negative value which can be deciphered by means
* of rkw_strerror() function
*/
int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
{
int fd;
int rc;
int len;
int ret;
uint32_t crc, fw_crc;
struct rkw_header_t rkw_info;
fd = open(filename, O_RDONLY);
if(fd < 0)
return -1;
rc = read(fd, &rkw_info, sizeof(rkw_info));
if (rc < (int)sizeof(rkw_info))
{
ret = -2;
goto end;
}
/* check if RKW is valid */
if (rkw_info.magic_number != RKLD_MAGIC)
{
ret = -3;
goto end;
}
/* check header crc if present */
if (rkw_info.load_options & RKW_HEADER_CRC)
{
crc = crc32_rkw((uint8_t *)&rkw_info, sizeof(rkw_info)-sizeof(uint32_t));
if (rkw_info.crc != crc)
{
ret = -4;
goto end;
}
}
/* check image size */
len = rkw_info.load_limit - rkw_info.load_address;
if (len > buffer_size)
{
ret = -5;
goto end;
}
/* check load address - we support loading only at 0x60000000 */
if (rkw_info.load_address != 0x60000000)
{
ret = -6;
goto end;
}
/* rockbox extension - we use one of reserved fields to store
* model number information. This prevents from loading
* rockbox RKW for different player.
*/
if (rkw_info.reserved0 != 0 && rkw_info.reserved0 != MODEL_NUMBER)
{
ret = -7;
goto end;
}
/* skip header */
lseek(fd, sizeof(rkw_info), SEEK_SET);
/* load image into buffer */
rc = read(fd, buf, len);
if(rc < len)
{
ret = -8;
goto end;
}
if (rkw_info.load_options & RKW_IMAGE_CRC)
{
rc = read(fd, &fw_crc, sizeof(uint32_t));
crc = crc32_rkw((uint8_t *)buf, len);
if (fw_crc != crc)
{
ret = -9;
goto end;
}
}
ret = len;
end:
close(fd);
return ret;
}