Add RKW firmware file format loader
Change-Id: I5283fdcdb8d263fd9375a6d29396f82650aeb686
This commit is contained in:
parent
f35e300304
commit
2f8b44aae2
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue