summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2012-03-02 16:29:42 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2012-03-04 00:34:26 +0100
commit2f8b44aae2827a7280dc0a8e5b46a9f33e5eea60 (patch)
treee14606096fa23091db5568d5312e2bda1ba176f3 /firmware
parentf35e300304388c30fdeb6493ec5e5e5bd52e3aab (diff)
downloadrockbox-2f8b44aae2827a7280dc0a8e5b46a9f33e5eea60.tar.gz
rockbox-2f8b44aae2827a7280dc0a8e5b46a9f33e5eea60.zip
Add RKW firmware file format loader
Change-Id: I5283fdcdb8d263fd9375a6d29396f82650aeb686
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/common/crc32-rkw.c111
-rw-r--r--firmware/export/rkw.h46
-rw-r--r--firmware/include/crc32-rkw.h27
-rw-r--r--firmware/target/arm/rk27xx/rkw-loader.c149
5 files changed, 337 insertions, 0 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 85705cb556..e8b0df0c31 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -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
diff --git a/firmware/common/crc32-rkw.c b/firmware/common/crc32-rkw.c
new file mode 100644
index 0000000000..48779f829d
--- /dev/null
+++ b/firmware/common/crc32-rkw.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;
+}
+
diff --git a/firmware/export/rkw.h b/firmware/export/rkw.h
new file mode 100644
index 0000000000..2101bd03b7
--- /dev/null
+++ b/firmware/export/rkw.h
@@ -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);
diff --git a/firmware/include/crc32-rkw.h b/firmware/include/crc32-rkw.h
new file mode 100644
index 0000000000..b33069e398
--- /dev/null
+++ b/firmware/include/crc32-rkw.h
@@ -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
diff --git a/firmware/target/arm/rk27xx/rkw-loader.c b/firmware/target/arm/rk27xx/rkw-loader.c
new file mode 100644
index 0000000000..328ad127d0
--- /dev/null
+++ b/firmware/target/arm/rk27xx/rkw-loader.c
@@ -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;
+}
+