summaryrefslogtreecommitdiff
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
137#ifdef MI4_FORMAT 137#ifdef MI4_FORMAT
138common/crc32-mi4.c 138common/crc32-mi4.c
139#endif 139#endif
140#ifdef RKW_FORMAT
141common/crc32-rkw.c
142#endif
140#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 143#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
141common/dir_uncached.c 144common/dir_uncached.c
142common/file.c 145common/file.c
@@ -1473,6 +1476,7 @@ target/arm/rk27xx/ftl-rk27xx.c
1473target/arm/rk27xx/nand-rk27xx.c 1476target/arm/rk27xx/nand-rk27xx.c
1474target/arm/rk27xx/usb-rk27xx.c 1477target/arm/rk27xx/usb-rk27xx.c
1475target/arm/rk27xx/lcdif-rk27xx.c 1478target/arm/rk27xx/lcdif-rk27xx.c
1479target/arm/rk27xx/rkw-loader.c
1476#ifndef BOOTLOADER 1480#ifndef BOOTLOADER
1477target/arm/rk27xx/pcm-rk27xx.c 1481target/arm/rk27xx/pcm-rk27xx.c
1478target/arm/rk27xx/debug-rk27xx.c 1482target/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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2012 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 "crc32-rkw.h"
22
23/* Slightly modified version of the crc32 algorithm generated with help of
24 * pycrc http://www.tty1.net/pycrc/index_en.html
25 * pycrc.py --width 32 --xor-in 0 --xor-out 0 --poly 0x04c10db7 \
26 * --reflect-in false --reflect-out false \
27 * --algorithm table-driven --table-idx-width 8 --generate c
28 */
29static const uint32_t crc_table[256] = {
30 0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9,
31 0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005,
32 0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61,
33 0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd,
34 0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9,
35 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75,
36 0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011,
37 0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd,
38 0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039,
39 0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5,
40 0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81,
41 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d,
42 0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49,
43 0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95,
44 0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1,
45 0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d,
46 0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae,
47 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072,
48 0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16,
49 0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca,
50 0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde,
51 0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02,
52 0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066,
53 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba,
54 0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e,
55 0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692,
56 0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6,
57 0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a,
58 0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e,
59 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2,
60 0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686,
61 0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a,
62 0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637,
63 0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb,
64 0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f,
65 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53,
66 0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47,
67 0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b,
68 0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff,
69 0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623,
70 0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7,
71 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b,
72 0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f,
73 0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3,
74 0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7,
75 0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b,
76 0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f,
77 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3,
78 0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640,
79 0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c,
80 0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8,
81 0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24,
82 0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30,
83 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec,
84 0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088,
85 0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654,
86 0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0,
87 0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c,
88 0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18,
89 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4,
90 0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0,
91 0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c,
92 0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668,
93 0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4
94};
95
96uint32_t crc32_rkw(const uint8_t *data, uint32_t len)
97{
98 uint8_t tbl_idx;
99 uint32_t crc = 0;
100
101 while (len--)
102 {
103 tbl_idx = ((crc >> 24) ^ *data) & 0xff;
104 crc = (crc_table[tbl_idx] ^ (crc << 8)) & 0xffffffff;
105
106 data++;
107 }
108
109 return crc;
110}
111
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2012 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 1
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 RKW_HEADER_CRC 0x40000000
25#define RKW_IMAGE_CRC 0x20000000
26
27struct rkw_header_t {
28 uint32_t magic_number; /* Magic number. 0x4C44524B */
29 uint32_t header_size; /* Size of the header */
30 uint32_t image_base; /* Base address of the firmware image */
31 uint32_t load_address; /* Load address */
32 uint32_t load_limit; /* End of the firmware image */
33 uint32_t bss_start; /* This is the start of .bss section of the firmware I suppose */
34 uint32_t reserved0; /* reserved - I've seen only zeros in this field so far */
35 uint32_t reserved1; /* reserved - I've seen only zeros in this field so far */
36 uint32_t entry_point; /* Entry point address */
37 uint32_t load_options; /* 0x80000000 - setup flag (I don't know what it means
38 * but is present in every RKW I saw),
39 * 0x40000000 - check header crc,
40 * 0x20000000 - check firmware crc
41 */
42 uint32_t crc; /* crc32 of the header (excluding crc32 field itself) */
43};
44
45const char *rkw_strerror(int8_t errno);
46int 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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2012 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#include <stdint.h>
21
22#ifndef _CRC32_RKW_H
23#define _CRC32_RKW_H
24
25uint32_t crc32_rkw (const uint8_t *src, uint32_t length);
26
27#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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2012 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 1
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 "config.h"
22#include "rkw.h"
23#include "crc32-rkw.h"
24#include "file.h"
25#include "panic.h"
26
27/* error strings sorted by number */
28/* error 0 is empty */
29static const char *err_str[] = {
30 "Loading OK",
31 "Can't open RKW file",
32 "Can't read RKW header",
33 "Invalid RKW magic number",
34 "RKW header CRC error",
35 "RKW file too big",
36 "RKW Load address mismatch",
37 "Bad model number",
38 "Error Reading File",
39 "RKW firmware CRC error"
40};
41
42const char *rkw_strerror(int8_t errno)
43{
44 if (-errno >= sizeof(err_str)/sizeof(err_str[0]) || errno > 0)
45 return "Unknown error";
46
47 return err_str[-errno];
48}
49
50/* loosely based on load_firmware()
51 * on success we return size loaded image
52 * on error we return negative value which can be deciphered by means
53 * of rkw_strerror() function
54 */
55int load_rkw(unsigned char* buf, const char* filename, int buffer_size)
56{
57 int fd;
58 int rc;
59 int len;
60 int ret;
61 uint32_t crc, fw_crc;
62 struct rkw_header_t rkw_info;
63
64 fd = open(filename, O_RDONLY);
65
66 if(fd < 0)
67 return -1;
68
69 rc = read(fd, &rkw_info, sizeof(rkw_info));
70 if (rc < (int)sizeof(rkw_info))
71 {
72 ret = -2;
73 goto end;
74 }
75
76 /* check if RKW is valid */
77 if (rkw_info.magic_number != RKLD_MAGIC)
78 {
79 ret = -3;
80 goto end;
81 }
82
83 /* check header crc if present */
84 if (rkw_info.load_options & RKW_HEADER_CRC)
85 {
86 crc = crc32_rkw((uint8_t *)&rkw_info, sizeof(rkw_info)-sizeof(uint32_t));
87 if (rkw_info.crc != crc)
88 {
89 ret = -4;
90 goto end;
91 }
92 }
93
94 /* check image size */
95 len = rkw_info.load_limit - rkw_info.load_address;
96 if (len > buffer_size)
97 {
98 ret = -5;
99 goto end;
100 }
101
102 /* check load address - we support loading only at 0x60000000 */
103 if (rkw_info.load_address != 0x60000000)
104 {
105 ret = -6;
106 goto end;
107 }
108
109 /* rockbox extension - we use one of reserved fields to store
110 * model number information. This prevents from loading
111 * rockbox RKW for different player.
112 */
113 if (rkw_info.reserved0 != 0 && rkw_info.reserved0 != MODEL_NUMBER)
114 {
115 ret = -7;
116 goto end;
117 }
118
119 /* skip header */
120 lseek(fd, sizeof(rkw_info), SEEK_SET);
121
122 /* load image into buffer */
123 rc = read(fd, buf, len);
124
125 if(rc < len)
126 {
127 ret = -8;
128 goto end;
129 }
130
131 if (rkw_info.load_options & RKW_IMAGE_CRC)
132 {
133 rc = read(fd, &fw_crc, sizeof(uint32_t));
134
135 crc = crc32_rkw((uint8_t *)buf, len);
136
137 if (fw_crc != crc)
138 {
139 ret = -9;
140 goto end;
141 }
142 }
143
144 ret = len;
145end:
146 close(fd);
147 return ret;
148}
149