summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootloader/sansaconnect.c140
-rw-r--r--firmware/target/arm/tms320dm320/boot.lds12
-rw-r--r--firmware/target/arm/tms320dm320/crt0.S6
3 files changed, 149 insertions, 9 deletions
diff --git a/bootloader/sansaconnect.c b/bootloader/sansaconnect.c
index a6559fee55..a87b23745f 100644
--- a/bootloader/sansaconnect.c
+++ b/bootloader/sansaconnect.c
@@ -33,6 +33,144 @@
33#include "power.h" 33#include "power.h"
34#include "loader_strerror.h" 34#include "loader_strerror.h"
35 35
36#define FLASH_BASE 0x00100000
37#define PARAMETERS_FLASH_OFFSET 0x00010000
38#define PARAMETERS_SIZE_BYTES 0x00010000
39#define PARAMETERS_NUM 32
40
41#define FLASH_WRITE(addr, val) *(volatile uint16_t *)(FLASH_BASE + addr) = val
42#define FLASH_READ(addr) *(volatile uint16_t *)(FLASH_BASE + addr)
43
44#define PARAMETER_TYPE_BINARY 0xF00FB00B
45#define PARAMETER_TYPE_LONGBIN 0xBEADFEAD
46#define PARAMETER_TYPE_STRING 0xBEEFFACE
47
48typedef struct
49{
50 uint32_t magic;
51 char name[60];
52 char value[192];
53} parameter_t;
54
55/* Cache all parameters because parameters are stored on a single erase block */
56static union
57{
58 parameter_t entry[PARAMETERS_NUM];
59 /* raw consists of parameter_t array and bootloader graphics */
60 uint16_t raw[PARAMETERS_SIZE_BYTES/sizeof(uint16_t)];
61} parameters;
62
63static void parameters_load_from_flash(void)
64{
65 uint32_t offset = PARAMETERS_FLASH_OFFSET;
66 uint16_t *dst = parameters.raw;
67
68 while (offset < (PARAMETERS_FLASH_OFFSET + PARAMETERS_SIZE_BYTES))
69 {
70 *dst++ = FLASH_READ(offset);
71 offset += sizeof(uint16_t);
72 }
73}
74
75void parameters_erase(void) __attribute__ ((section(".icode")));
76void parameters_erase(void)
77{
78 uint32_t offset = PARAMETERS_FLASH_OFFSET;
79
80 while (offset < (PARAMETERS_FLASH_OFFSET + PARAMETERS_SIZE_BYTES))
81 {
82 if (FLASH_READ(offset) != 0xFFFF)
83 {
84 /* Found programmed halfword */
85 break;
86 }
87 offset += sizeof(uint16_t);
88 }
89
90 if (offset >= (PARAMETERS_FLASH_OFFSET + PARAMETERS_SIZE_BYTES))
91 {
92 /* Flash is already erased */
93 return;
94 }
95
96 /* Execute Block Erase sequence */
97 FLASH_WRITE(0xAAA, 0xAA);
98 FLASH_WRITE(0x554, 0x55);
99 FLASH_WRITE(0xAAA, 0x80);
100 FLASH_WRITE(0xAAA, 0xAA);
101 FLASH_WRITE(0x554, 0x55);
102 FLASH_WRITE(PARAMETERS_FLASH_OFFSET, 0x30);
103
104 /* Erase finishes once we read 0xFFFF on previously programmed halfword
105 * Typical block erase time is 0.7 s, maximum 15 s. Do not check the
106 * timeout here because we have to wait until the erase finishes as most
107 * of Rockbox bootloader code executes from flash.
108 */
109 do
110 {
111 /* Discard caches to force reads from memory */
112 commit_discard_idcache();
113 }
114 while (FLASH_READ(offset) != 0xFFFF);
115}
116
117void parameters_write_to_flash(void) __attribute__ ((section(".icode")));
118void parameters_write_to_flash(void)
119{
120 uint16_t *src = parameters.raw;
121 uint32_t offset = PARAMETERS_FLASH_OFFSET;
122
123 while (offset < (PARAMETERS_FLASH_OFFSET + PARAMETERS_SIZE_BYTES))
124 {
125 if (FLASH_READ(offset) != *src)
126 {
127 /* Program halfword */
128 FLASH_WRITE(0xAAA, 0xAA);
129 FLASH_WRITE(0x554, 0x55);
130 FLASH_WRITE(0xAAA, 0xA0);
131 FLASH_WRITE(offset, *src);
132
133 /* Word programming time typical is 14 us, maximum 330 us */
134 do
135 {
136 /* Discard caches to force reads from memory */
137 commit_discard_idcache();
138 }
139 while (FLASH_READ(offset) != *src);
140 }
141 offset += sizeof(uint16_t);
142 src++;
143 }
144}
145
146static void clear_recoverzap(void)
147{
148 int i;
149 bool needs_reflash = false;
150
151 parameters_load_from_flash();
152 for (i = 0; i < PARAMETERS_NUM; i++)
153 {
154 if ((parameters.entry[i].magic == PARAMETER_TYPE_STRING) &&
155 (!strcmp("recoverzap", parameters.entry[i].name)))
156 {
157 memset(&parameters.entry[i], 0xFF, sizeof(parameter_t));
158 needs_reflash = true;
159 }
160 }
161
162 if (needs_reflash)
163 {
164 int cpsr = disable_interrupt_save(IRQ_FIQ_STATUS);
165 printf("Erasing OF parameters memory");
166 parameters_erase();
167 printf("Flashing OF parameters");
168 parameters_write_to_flash();
169 printf("Cleared recoverzap parameter");
170 restore_interrupt(cpsr);
171 }
172}
173
36extern void show_logo(void); 174extern void show_logo(void);
37 175
38void main(void) 176void main(void)
@@ -69,6 +207,8 @@ void main(void)
69 printf("Rockbox boot loader"); 207 printf("Rockbox boot loader");
70 printf("Version %s", rbversion); 208 printf("Version %s", rbversion);
71 209
210 clear_recoverzap();
211
72 ret = storage_init(); 212 ret = storage_init();
73 if(ret) 213 if(ret)
74 printf("SD error: %d", ret); 214 printf("SD error: %d", ret);
diff --git a/firmware/target/arm/tms320dm320/boot.lds b/firmware/target/arm/tms320dm320/boot.lds
index c59cc7f514..2db687d533 100644
--- a/firmware/target/arm/tms320dm320/boot.lds
+++ b/firmware/target/arm/tms320dm320/boot.lds
@@ -38,12 +38,12 @@ STARTUP(target/arm/tms320dm320/crt0.o)
38 38
39#ifdef SANSA_CONNECT 39#ifdef SANSA_CONNECT
40/* Offset in flash from beginning, we don't want overwrite OF bootloader 40/* Offset in flash from beginning, we don't want overwrite OF bootloader
41 due to recovery mode and more importantly - hardware block protection. 41 * due to recovery mode and more importantly - hardware block protection.
42 This offset makes Rockbox bootloader a replacement for OF vmlinux. 42 * Rockbox bootloader is flashed into kernel partition and chainloaded
43 In .srr file header add any valid memory address from following 43 * from OF bootloader via Arbitrary Code Execution exploit. The first
44 <0x1000000; 0x1300180) u (0x131EAF4; 0x1420000) u (0x1440000; 0x5000000> 44 * instruction must be position independent as Rockbox bootloader will be
45 ensuring that complete bootloader fits in. 45 * copied to RAM at 0x01000000 and executed from RAM.
46 Entry point in .srr file should be equal to _loadaddress. */ 46 */
47#define FLASHSIZE 0x00400000 47#define FLASHSIZE 0x00400000
48#define FLASHMEMORIG 0x00120010 48#define FLASHMEMORIG 0x00120010
49/* Kernel partition is 2 M, srr header is 16 bytes, sig is 2048 bytes */ 49/* Kernel partition is 2 M, srr header is 16 bytes, sig is 2048 bytes */
diff --git a/firmware/target/arm/tms320dm320/crt0.S b/firmware/target/arm/tms320dm320/crt0.S
index 9f2c8dbe04..e57e28a470 100644
--- a/firmware/target/arm/tms320dm320/crt0.S
+++ b/firmware/target/arm/tms320dm320/crt0.S
@@ -201,14 +201,14 @@ _start:
201 mov r3, #CACHE_NONE 201 mov r3, #CACHE_NONE
202 bl map_section 202 bl map_section
203 203
204 /* Enable caching for FLASH */ 204 /* Enable write-through caching for FLASH */
205 ldr r0, =_flash_start 205 ldr r0, =_flash_start
206 ldr r1, =_flash_start 206 ldr r1, =_flash_start
207 ldr r2, =_flash_sizem 207 ldr r2, =_flash_sizem
208 mov r3, #CACHE_ALL 208 mov r3, #(CACHE_ALL & ~BUFFERED)
209 bl map_section 209 bl map_section
210 210
211 /* Enable caching for RAM */ 211 /* Enable write-back caching for RAM */
212 ldr r0, =_sdram_start 212 ldr r0, =_sdram_start
213 ldr r1, =_sdram_start 213 ldr r1, =_sdram_start
214 ldr r2, =_sdram_sizem 214 ldr r2, =_sdram_sizem