diff options
-rw-r--r-- | firmware/SOURCES | 4 | ||||
-rw-r--r-- | firmware/common/crc32-rkw.c | 111 | ||||
-rw-r--r-- | firmware/export/rkw.h | 46 | ||||
-rw-r--r-- | firmware/include/crc32-rkw.h | 27 | ||||
-rw-r--r-- | firmware/target/arm/rk27xx/rkw-loader.c | 149 |
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 |
138 | common/crc32-mi4.c | 138 | common/crc32-mi4.c |
139 | #endif | 139 | #endif |
140 | #ifdef RKW_FORMAT | ||
141 | common/crc32-rkw.c | ||
142 | #endif | ||
140 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 143 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
141 | common/dir_uncached.c | 144 | common/dir_uncached.c |
142 | common/file.c | 145 | common/file.c |
@@ -1473,6 +1476,7 @@ target/arm/rk27xx/ftl-rk27xx.c | |||
1473 | target/arm/rk27xx/nand-rk27xx.c | 1476 | target/arm/rk27xx/nand-rk27xx.c |
1474 | target/arm/rk27xx/usb-rk27xx.c | 1477 | target/arm/rk27xx/usb-rk27xx.c |
1475 | target/arm/rk27xx/lcdif-rk27xx.c | 1478 | target/arm/rk27xx/lcdif-rk27xx.c |
1479 | target/arm/rk27xx/rkw-loader.c | ||
1476 | #ifndef BOOTLOADER | 1480 | #ifndef BOOTLOADER |
1477 | target/arm/rk27xx/pcm-rk27xx.c | 1481 | target/arm/rk27xx/pcm-rk27xx.c |
1478 | target/arm/rk27xx/debug-rk27xx.c | 1482 | 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 @@ | |||
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 | */ | ||
29 | static 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 | |||
96 | uint32_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 | |||
27 | struct 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 | |||
45 | const char *rkw_strerror(int8_t errno); | ||
46 | 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 @@ | |||
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 | |||
25 | uint32_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 */ | ||
29 | static 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 | |||
42 | const 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 | */ | ||
55 | int 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; | ||
145 | end: | ||
146 | close(fd); | ||
147 | return ret; | ||
148 | } | ||
149 | |||