diff options
-rw-r--r-- | bootloader/sansaconnect.c | 140 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/boot.lds | 12 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/crt0.S | 6 |
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 | |||
48 | typedef 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 */ | ||
56 | static 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 | |||
63 | static 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 | |||
75 | void parameters_erase(void) __attribute__ ((section(".icode"))); | ||
76 | void 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 | |||
117 | void parameters_write_to_flash(void) __attribute__ ((section(".icode"))); | ||
118 | void 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 | |||
146 | static 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(¶meters.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 | |||
36 | extern void show_logo(void); | 174 | extern void show_logo(void); |
37 | 175 | ||
38 | void main(void) | 176 | void 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 |