diff options
29 files changed, 3349 insertions, 1 deletions
diff --git a/flash/README b/flash/README index 304360caba..9f77dd502f 100644 --- a/flash/README +++ b/flash/README | |||
@@ -1 +1,7 @@ | |||
1 | Readme | 1 | (c) 2003 by Jörg Hohensohn |
2 | |||
3 | Sourcecode for the flash "infrastructure" | ||
4 | Please bear in mind that these are powerful tools, don't fool with them! | ||
5 | |||
6 | For most up-to-date info about flashing see: | ||
7 | http://rockbox.haxx.se/docs/flash.html | ||
diff --git a/flash/bootloader/Makefile b/flash/bootloader/Makefile new file mode 100644 index 0000000000..ae56cf9425 --- /dev/null +++ b/flash/bootloader/Makefile | |||
@@ -0,0 +1,78 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | CC = sh-elf-gcc | ||
11 | LD = sh-elf-ld | ||
12 | AR = sh-elf-ar | ||
13 | AS = sh-elf-as | ||
14 | OC = sh-elf-objcopy | ||
15 | |||
16 | FIRMWARE := ../../firmware | ||
17 | TOOLSDIR=../../tools | ||
18 | |||
19 | TARGET = bootloader | ||
20 | LDS := $(TARGET).lds | ||
21 | |||
22 | |||
23 | ifndef PLATFORM | ||
24 | not_configured: | ||
25 | @echo "No platform given." | ||
26 | @echo "Use make PLATFORM=PLAYER|RECORDER|RECORDER|FM {NO_ROM=1}" | ||
27 | ##else | ||
28 | ##configured: | ||
29 | ## @echo "Building bootloader for platform "$(PLATFORM) | ||
30 | endif | ||
31 | |||
32 | |||
33 | INCLUDES= -I$(FIRMWARE)/export -I. -I$(OBJDIR) | ||
34 | DEFINES= -DPLATFORM_$(PLATFORM) | ||
35 | |||
36 | OBJDIR := . | ||
37 | |||
38 | CFLAGS = -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(DEFINES) | ||
39 | AFLAGS += -small -relax | ||
40 | |||
41 | |||
42 | ifdef DEBUG | ||
43 | DEFINES := -DDEBUG | ||
44 | CFLAGS += -g | ||
45 | endif | ||
46 | |||
47 | SRC := $(wildcard *.c) | ||
48 | |||
49 | OBJS := $(SRC:%.c=$(OBJDIR)/%.o) | ||
50 | |||
51 | ifdef NO_ROM | ||
52 | LINKFILE = $(OBJDIR)/no_rom.lds | ||
53 | ORIGIN = 0 | ||
54 | DEFINES += -DNO_ROM | ||
55 | else | ||
56 | LINKFILE = $(OBJDIR)/$(TARGET).lds | ||
57 | ORIGIN = FFFF500 | ||
58 | endif | ||
59 | |||
60 | $(OBJDIR)/$(TARGET).bin : $(OBJDIR)/$(TARGET).elf | ||
61 | $(OC) -O binary $(OBJDIR)/$(TARGET).elf $(OBJDIR)/$(TARGET).bin | ||
62 | $(TOOLSDIR)/sh2d $(OBJDIR)/$(TARGET).bin -o $(ORIGIN) > $(OBJDIR)/$(TARGET).asm | ||
63 | ifndef NO_ROM | ||
64 | $(TOOLSDIR)/scramble $(OBJDIR)/$(TARGET).bin $(OBJDIR)/$(TARGET).ajz | ||
65 | endif | ||
66 | |||
67 | $(OBJDIR)/$(TARGET).elf : $(OBJS) | ||
68 | $(CC) -Os -nostdlib -o $(OBJDIR)/$(TARGET).elf -L$(OBJDIR) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$(TARGET).map | ||
69 | |||
70 | |||
71 | clean: | ||
72 | -rm -f \ | ||
73 | $(OBJS) \ | ||
74 | $(OBJDIR)/$(TARGET).asm \ | ||
75 | $(OBJDIR)/$(TARGET).bin \ | ||
76 | $(OBJDIR)/$(TARGET).ajz \ | ||
77 | $(OBJDIR)/$(TARGET).elf \ | ||
78 | $(OBJDIR)/$(TARGET).map | ||
diff --git a/flash/bootloader/README b/flash/bootloader/README new file mode 100644 index 0000000000..16c27d9876 --- /dev/null +++ b/flash/bootloader/README | |||
@@ -0,0 +1,4 @@ | |||
1 | (c) 2003 by Jörg Hohensohn | ||
2 | |||
3 | This is the source code for the flash bootloader. | ||
4 | It give the dual boot feature, decompresses one of two software images. | ||
diff --git a/flash/bootloader/bootloader.c b/flash/bootloader/bootloader.c new file mode 100644 index 0000000000..7179bbef95 --- /dev/null +++ b/flash/bootloader/bootloader.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2003 by Jörg Hohensohn | ||
11 | * | ||
12 | * Second-level bootloader, with dual-boot feature by holding F1/Menu | ||
13 | * This is the image being descrambled and executed by the boot ROM. | ||
14 | * It's task is to copy Rockbox from Flash to DRAM. | ||
15 | * The image(s) in flash may optionally be compressed with UCL 2e | ||
16 | * | ||
17 | * All files in this archive are subject to the GNU General Public License. | ||
18 | * See the file COPYING in the source tree root for full license agreement. | ||
19 | * | ||
20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
21 | * KIND, either express or implied. | ||
22 | * | ||
23 | ****************************************************************************/ | ||
24 | |||
25 | #include "sh7034.h" | ||
26 | #include "bootloader.h" | ||
27 | |||
28 | |||
29 | #ifdef NO_ROM | ||
30 | // start with the vector table | ||
31 | UINT32 vectors[] __attribute__ ((section (".vectors"))) = | ||
32 | { | ||
33 | (UINT32)_main, // entry point, the copy routine | ||
34 | (UINT32)(end_stack - 1), // initial stack pointer | ||
35 | FLASH_BASE + 0x200, // source of image in flash | ||
36 | (UINT32)total_size, // size of image | ||
37 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||
38 | 0x03020080 // mask and version (just as a suggestion) | ||
39 | }; | ||
40 | #else | ||
41 | // our binary has to start with a vector to the entry point | ||
42 | tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main}; | ||
43 | #endif | ||
44 | |||
45 | #ifdef NO_ROM // some code which is only needed for the romless variant | ||
46 | void _main(void) | ||
47 | { | ||
48 | UINT32* pSrc; | ||
49 | UINT32* pDest; | ||
50 | UINT32* pEnd; | ||
51 | /* | ||
52 | asm volatile ("ldc %0,sr" : : "r"(0xF0)); // disable interrupts | ||
53 | asm volatile ("mov.l @%0,r15" : : "r"(4)); // load stack | ||
54 | asm volatile ("ldc %0,vbr" : : "r"(0)); // load vector base | ||
55 | */ | ||
56 | // copy everything to IRAM and continue there | ||
57 | pSrc = begin_iramcopy; | ||
58 | pDest = begin_text; | ||
59 | pEnd = pDest + (begin_stack - begin_text); | ||
60 | |||
61 | do | ||
62 | { | ||
63 | *pDest++ = *pSrc++; | ||
64 | } | ||
65 | while (pDest < pEnd); | ||
66 | |||
67 | main(); // jump to the real main() | ||
68 | } | ||
69 | |||
70 | |||
71 | void BootInit(void) | ||
72 | { | ||
73 | // inits from the boot ROM, whether they make sense or not | ||
74 | PBDR &= 0xFFBF; // LED off (0x131E) | ||
75 | PBCR2 = 0; // all GPIO | ||
76 | PBIOR |= 0x40; // LED output | ||
77 | PBIOR &= 0xFFF1; // LCD lines input | ||
78 | |||
79 | // init DRAM like the boot ROM does | ||
80 | PACR2 &= 0xFFFB; | ||
81 | PACR2 |= 0x0008; | ||
82 | CASCR = 0xAF; | ||
83 | BCR |= 0x8000; | ||
84 | WCR1 &= 0xFDFD; | ||
85 | DCR = 0x0E00; | ||
86 | RCR = 0x5AB0; | ||
87 | RTCOR = 0x9605; | ||
88 | RTCSR = 0xA518; | ||
89 | } | ||
90 | #endif // #ifdef NO_ROM | ||
91 | |||
92 | |||
93 | int main(void) | ||
94 | { | ||
95 | int nButton; | ||
96 | |||
97 | PlatformInit(); // model-specific inits | ||
98 | |||
99 | nButton = ButtonPressed(); | ||
100 | |||
101 | if (nButton == 3) | ||
102 | { // F3 means start monitor | ||
103 | MiniMon(); | ||
104 | } | ||
105 | else | ||
106 | { | ||
107 | tImage* pImage; | ||
108 | pImage = GetStartImage(nButton); // which image | ||
109 | DecompressStart(pImage); // move into place and start it | ||
110 | } | ||
111 | |||
112 | return 0; // I guess we won't return ;-) | ||
113 | } | ||
114 | |||
115 | |||
116 | // init code that is specific to certain platform | ||
117 | void PlatformInit(void) | ||
118 | { | ||
119 | #ifdef NO_ROM | ||
120 | BootInit(); // if not started by boot ROM, we need to init what it did | ||
121 | #endif | ||
122 | |||
123 | #if defined PLATFORM_PLAYER | ||
124 | BRR1 = 0x0019; // 14400 Baud for monitor | ||
125 | if (FW_VERSION > 451) // "new" Player? | ||
126 | { | ||
127 | PBDR &= ~0x10; // set PB4 to 0 to power-up the harddisk early | ||
128 | PBIOR |= 0x10; // make PB4 an output | ||
129 | } | ||
130 | #elif defined PLATFORM_RECORDER | ||
131 | BRR1 = 0x0002; // 115200 Baud for monitor | ||
132 | if (ReadADC(7) > 0x100) // charger plugged? | ||
133 | { // switch off the HD, else a flat battery may not start | ||
134 | PACR2 &= 0xFBFF; // GPIO for PA5 | ||
135 | PAIOR |= 0x20; // make PA5 an output (low by default) | ||
136 | } | ||
137 | #elif defined PLATFORM_FM | ||
138 | BRR1 = 0x0002; // 115200 Baud for monitor | ||
139 | PBDR |= 0x20; // set PB5 to keep power (fixes the ON-holding problem) | ||
140 | PBIOR |= 0x20; // make PB5 an output | ||
141 | if (ReadADC(0) < 0x1FF) // charger plugged? | ||
142 | { | ||
143 | // how do we switch this off? | ||
144 | } | ||
145 | #endif | ||
146 | |||
147 | // platform-independent inits | ||
148 | DCR |= 0x1000; // enable burst mode on DRAM | ||
149 | BCR |= 0x2000; // activate Warp mode (simultaneous internal and external mem access) | ||
150 | } | ||
151 | |||
152 | |||
153 | // Thinned out version of the UCL 2e decompression sourcecode | ||
154 | // Original (C) Markus F.X.J Oberhumer under GNU GPL license | ||
155 | #define GETBIT(bb, src, ilen) \ | ||
156 | (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1) | ||
157 | |||
158 | int ucl_nrv2e_decompress_8( | ||
159 | const UINT8 *src, UINT8 *dst, UINT32* dst_len) | ||
160 | { | ||
161 | UINT32 bb = 0; | ||
162 | unsigned ilen = 0, olen = 0, last_m_off = 1; | ||
163 | |||
164 | for (;;) | ||
165 | { | ||
166 | unsigned m_off, m_len; | ||
167 | |||
168 | while (GETBIT(bb,src,ilen)) | ||
169 | { | ||
170 | dst[olen++] = src[ilen++]; | ||
171 | } | ||
172 | m_off = 1; | ||
173 | for (;;) | ||
174 | { | ||
175 | m_off = m_off*2 + GETBIT(bb,src,ilen); | ||
176 | if (GETBIT(bb,src,ilen)) break; | ||
177 | m_off = (m_off-1)*2 + GETBIT(bb,src,ilen); | ||
178 | } | ||
179 | if (m_off == 2) | ||
180 | { | ||
181 | m_off = last_m_off; | ||
182 | m_len = GETBIT(bb,src,ilen); | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | m_off = (m_off-3)*256 + src[ilen++]; | ||
187 | if (m_off == 0xffffffff) | ||
188 | break; | ||
189 | m_len = (m_off ^ 0xffffffff) & 1; | ||
190 | m_off >>= 1; | ||
191 | last_m_off = ++m_off; | ||
192 | } | ||
193 | if (m_len) | ||
194 | m_len = 1 + GETBIT(bb,src,ilen); | ||
195 | else if (GETBIT(bb,src,ilen)) | ||
196 | m_len = 3 + GETBIT(bb,src,ilen); | ||
197 | else | ||
198 | { | ||
199 | m_len++; | ||
200 | do { | ||
201 | m_len = m_len*2 + GETBIT(bb,src,ilen); | ||
202 | } while (!GETBIT(bb,src,ilen)); | ||
203 | m_len += 3; | ||
204 | } | ||
205 | m_len += (m_off > 0x500); | ||
206 | { | ||
207 | const UINT8 *m_pos; | ||
208 | m_pos = dst + olen - m_off; | ||
209 | dst[olen++] = *m_pos++; | ||
210 | do dst[olen++] = *m_pos++; while (--m_len > 0); | ||
211 | } | ||
212 | } | ||
213 | *dst_len = olen; | ||
214 | |||
215 | return ilen; | ||
216 | } | ||
217 | |||
218 | |||
219 | // move the image into place and start it | ||
220 | void DecompressStart(tImage* pImage) | ||
221 | { | ||
222 | UINT32* pSrc; | ||
223 | UINT32* pDest; | ||
224 | |||
225 | pSrc = pImage->image; | ||
226 | pDest = pImage->pDestination; | ||
227 | |||
228 | if (pSrc != pDest) // if not linked to that flash address | ||
229 | { | ||
230 | if (pImage->flags & IF_UCL_2E) | ||
231 | { // UCL compressed, algorithm 2e | ||
232 | UINT32 dst_len; // dummy | ||
233 | ucl_nrv2e_decompress_8((UINT8*)pSrc, (UINT8*)pDest, &dst_len); | ||
234 | } | ||
235 | else | ||
236 | { // uncompressed, copy it | ||
237 | UINT32 size = pImage->size; | ||
238 | UINT32* pEnd; | ||
239 | size = (size + 3) / 4; // round up to 32bit-words | ||
240 | pEnd = pDest + size; | ||
241 | |||
242 | do | ||
243 | { | ||
244 | *pDest++ = *pSrc++; | ||
245 | } | ||
246 | while (pDest < pEnd); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | pImage->pExecute(); | ||
251 | } | ||
252 | |||
253 | |||
254 | int ReadADC(int channel) | ||
255 | { | ||
256 | // after channel 3, the ports wrap and get re-used | ||
257 | volatile UINT16* pResult = (UINT16*)(ADDRAH_ADDR + 2 * (channel & 0x03)); | ||
258 | int timeout = 266; // conversion takes 266 clock cycles | ||
259 | |||
260 | ADCSR = 0x20 | channel; // start single conversion | ||
261 | while (((ADCSR & 0x80) == 0) && (--timeout)); // 6 instructions per round | ||
262 | |||
263 | return (timeout == 0) ? -1 : *pResult>>6; | ||
264 | } | ||
265 | |||
266 | |||
267 | // This function is platform-dependent, | ||
268 | // until I figure out how to distinguish at runtime. | ||
269 | int ButtonPressed(void) // return 1,2,3 for F1,F2,F3, 0 if none pressed | ||
270 | { | ||
271 | int value = ReadADC(CHANNEL); | ||
272 | |||
273 | if (value >= F1_LOWER && value <= F1_UPPER) // in range | ||
274 | return 1; | ||
275 | else if (value >= F2_LOWER && value <= F2_UPPER) // in range | ||
276 | return 2; | ||
277 | else if (value >= F3_LOWER && value <= F3_UPPER) // in range | ||
278 | return 3; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | // Determine the image to be started | ||
285 | tImage* GetStartImage(int nPreferred) | ||
286 | { | ||
287 | tImage* pImage1; | ||
288 | tImage* pImage2 = NULL; // default to not present | ||
289 | UINT32 pos; | ||
290 | UINT32* pFlash = (UINT32*)FLASH_BASE; | ||
291 | |||
292 | // determine the first image position | ||
293 | pos = pFlash[2] + pFlash[3]; // position + size of the bootloader = after it | ||
294 | pos = (pos + 3) & ~3; // be shure it's 32 bit aligned | ||
295 | |||
296 | pImage1 = (tImage*)pos; | ||
297 | |||
298 | if (pImage1->size != 0) | ||
299 | { // check for second image | ||
300 | pos = (UINT32)(&pImage1->image) + pImage1->size; | ||
301 | pImage2 = (tImage*)pos; | ||
302 | |||
303 | // does it make sense? (not in FF or 00 erazed space) | ||
304 | if (pImage2->pDestination == (void*)0xFFFFFFFF | ||
305 | || pImage2->size == 0xFFFFFFFF | ||
306 | || pImage2->pExecute == (void*)0xFFFFFFFF | ||
307 | || pImage2->flags == 0xFFFFFFFF | ||
308 | || pImage2->pDestination == NULL) // size, execute and flags can legally be 0 | ||
309 | { | ||
310 | pImage2 = NULL; // invalidate | ||
311 | } | ||
312 | } | ||
313 | |||
314 | if (pImage2 == NULL || nPreferred == 1) | ||
315 | { // no second image or overridden: return the first | ||
316 | return pImage1; | ||
317 | } | ||
318 | |||
319 | return pImage2; // return second image | ||
320 | } | ||
321 | |||
322 | // diagnostic functions | ||
323 | |||
324 | void SetLed(BOOL bOn) | ||
325 | { | ||
326 | if (bOn) | ||
327 | PBDR |= 0x40; | ||
328 | else | ||
329 | PBDR &= ~0x40; | ||
330 | } | ||
331 | |||
332 | |||
333 | void UartInit(void) | ||
334 | { | ||
335 | PBIOR &= 0xFBFF; // input: RXD1 remote pin | ||
336 | PBCR1 |= 0x00A0; // set PB3+PB2 to UART | ||
337 | PBCR1 &= 0xFFAF; // clear bits 6, 4 -> UART | ||
338 | SMR1 = 0x0000; // async format 8N1, baud generator input is CPU clock | ||
339 | SCR1 = 0x0030; // transmit+receive enable | ||
340 | PBCR1 &= 0x00FF; // set bit 12...15 as GPIO | ||
341 | SSR1 &= 0x00BF; // clear bit 6 (RDRF, receive data register full) | ||
342 | } | ||
343 | |||
344 | |||
345 | UINT8 UartRead(void) | ||
346 | { | ||
347 | UINT8 byte; | ||
348 | while (!(SSR1 & SCI_RDRF)); // wait for char to be available | ||
349 | byte = RDR1; | ||
350 | SSR1 &= ~SCI_RDRF; | ||
351 | return byte; | ||
352 | } | ||
353 | |||
354 | |||
355 | void UartWrite(UINT8 byte) | ||
356 | { | ||
357 | while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty | ||
358 | TDR1 = byte; | ||
359 | SSR1 &= ~SCI_TDRE; | ||
360 | } | ||
361 | |||
362 | |||
363 | // include the mini monitor as a rescue feature, started with F3 | ||
364 | void MiniMon(void) | ||
365 | { | ||
366 | UINT8 cmd; | ||
367 | UINT32 addr; | ||
368 | UINT32 size; | ||
369 | UINT32 content; | ||
370 | volatile UINT8* paddr = NULL; | ||
371 | volatile UINT8* pflash = NULL; // flash base address | ||
372 | |||
373 | UartInit(); | ||
374 | |||
375 | while (1) | ||
376 | { | ||
377 | cmd = UartRead(); | ||
378 | switch (cmd) | ||
379 | { | ||
380 | case BAUDRATE: | ||
381 | content = UartRead(); | ||
382 | UartWrite(cmd); // acknowledge by returning the command value | ||
383 | while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate | ||
384 | BRR1 = content; | ||
385 | break; | ||
386 | |||
387 | case ADDRESS: | ||
388 | addr = (UartRead() << 24) | (UartRead() << 16) | (UartRead() << 8) | UartRead(); | ||
389 | paddr = (UINT8*)addr; | ||
390 | pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align | ||
391 | UartWrite(cmd); // acknowledge by returning the command value | ||
392 | break; | ||
393 | |||
394 | case BYTE_READ: | ||
395 | content = *paddr++; | ||
396 | UartWrite(content); // the content is the ack | ||
397 | break; | ||
398 | |||
399 | case BYTE_WRITE: | ||
400 | content = UartRead(); | ||
401 | *paddr++ = content; | ||
402 | UartWrite(cmd); // acknowledge by returning the command value | ||
403 | break; | ||
404 | |||
405 | case BYTE_READ16: | ||
406 | size = 16; | ||
407 | while (size--) | ||
408 | { | ||
409 | content = *paddr++; | ||
410 | UartWrite(content); // the content is the ack | ||
411 | } | ||
412 | break; | ||
413 | |||
414 | case BYTE_WRITE16: | ||
415 | size = 16; | ||
416 | while (size--) | ||
417 | { | ||
418 | content = UartRead(); | ||
419 | *paddr++ = content; | ||
420 | } | ||
421 | UartWrite(cmd); // acknowledge by returning the command value | ||
422 | break; | ||
423 | |||
424 | case BYTE_FLASH: | ||
425 | content = UartRead(); | ||
426 | pflash[0x5555] = 0xAA; // set flash to command mode | ||
427 | pflash[0x2AAA] = 0x55; | ||
428 | pflash[0x5555] = 0xA0; // byte program command | ||
429 | *paddr++ = content; | ||
430 | UartWrite(cmd); // acknowledge by returning the command value | ||
431 | break; | ||
432 | |||
433 | case BYTE_FLASH16: | ||
434 | size = 16; | ||
435 | while (size--) | ||
436 | { | ||
437 | content = UartRead(); | ||
438 | pflash[0x5555] = 0xAA; // set flash to command mode | ||
439 | pflash[0x2AAA] = 0x55; | ||
440 | pflash[0x5555] = 0xA0; // byte program command | ||
441 | *paddr++ = content; | ||
442 | } | ||
443 | UartWrite(cmd); // acknowledge by returning the command value | ||
444 | break; | ||
445 | |||
446 | case HALFWORD_READ: | ||
447 | content = *(UINT16*)paddr; | ||
448 | paddr += 2; | ||
449 | UartWrite(content >> 8); // highbyte | ||
450 | UartWrite(content & 0xFF); // lowbyte | ||
451 | break; | ||
452 | |||
453 | case HALFWORD_WRITE: | ||
454 | content = UartRead() << 8 | UartRead(); | ||
455 | *(UINT16*)paddr = content; | ||
456 | paddr += 2; | ||
457 | UartWrite(cmd); // acknowledge by returning the command value | ||
458 | break; | ||
459 | |||
460 | case EXECUTE: | ||
461 | { | ||
462 | tpFunc pFunc = (tpFunc)paddr; | ||
463 | pFunc(); | ||
464 | UartWrite(cmd); // acknowledge by returning the command value | ||
465 | } | ||
466 | break; | ||
467 | |||
468 | case VERSION: | ||
469 | UartWrite(1); // return our version number | ||
470 | break; | ||
471 | |||
472 | default: | ||
473 | { | ||
474 | SetLed(TRUE); | ||
475 | UartWrite(~cmd); // error acknowledge | ||
476 | } | ||
477 | |||
478 | } // case | ||
479 | } // while (1) | ||
480 | } | ||
diff --git a/flash/bootloader/bootloader.h b/flash/bootloader/bootloader.h new file mode 100644 index 0000000000..eee61c4809 --- /dev/null +++ b/flash/bootloader/bootloader.h | |||
@@ -0,0 +1,111 @@ | |||
1 | #ifndef NULL | ||
2 | #define NULL ((void*)0) | ||
3 | #endif | ||
4 | |||
5 | #define TRUE 1 | ||
6 | #define FALSE 0 | ||
7 | |||
8 | // scalar types | ||
9 | typedef unsigned char UINT8; | ||
10 | typedef unsigned short UINT16; | ||
11 | typedef unsigned long UINT32; | ||
12 | typedef int BOOL; | ||
13 | |||
14 | typedef void(*tpFunc)(void); // type for execute | ||
15 | typedef int(*tpMain)(void); // type for start vector to main() | ||
16 | |||
17 | |||
18 | // structure of an image in the flash | ||
19 | typedef struct | ||
20 | { | ||
21 | UINT32* pDestination; // address to copy it to | ||
22 | UINT32 size; // how many bytes of payload (to the next header) | ||
23 | tpFunc pExecute; // entry point | ||
24 | UINT32 flags; // uncompressed or compressed | ||
25 | // end of header, now comes the payload | ||
26 | UINT32 image[]; // the binary image starts here | ||
27 | // after the payload, the next header may follow, all 0xFF if none | ||
28 | } tImage; | ||
29 | |||
30 | // flags valid for image header | ||
31 | #define IF_NONE 0x00000000 | ||
32 | #define IF_UCL_2E 0x00000001 // image is compressed with UCL, algorithm 2e | ||
33 | |||
34 | |||
35 | // resolve platform dependency of F1 button check | ||
36 | #if defined PLATFORM_PLAYER | ||
37 | #define CHANNEL 1 | ||
38 | #define F1_LOWER 0 // this is the "Menu" key | ||
39 | #define F1_UPPER 384 | ||
40 | #define F2_LOWER 1024 // not present | ||
41 | #define F2_UPPER 1024 | ||
42 | #define F3_LOWER 1024 | ||
43 | #define F3_UPPER 1024 | ||
44 | #elif defined PLATFORM_RECORDER | ||
45 | #define CHANNEL 4 | ||
46 | #define F1_LOWER 250 | ||
47 | #define F1_UPPER 499 | ||
48 | #define F2_LOWER 500 | ||
49 | #define F2_UPPER 699 | ||
50 | #define F3_LOWER 900 | ||
51 | #define F3_UPPER 1023 | ||
52 | #elif defined PLATFORM_FM | ||
53 | #define CHANNEL 4 | ||
54 | #define F1_LOWER 150 | ||
55 | #define F1_UPPER 384 | ||
56 | #define F2_LOWER 385 | ||
57 | #define F2_UPPER 544 | ||
58 | #define F3_LOWER 700 | ||
59 | #define F3_UPPER 1023 | ||
60 | #else | ||
61 | #error ("No platform given!") | ||
62 | #endif | ||
63 | |||
64 | #define FLASH_BASE 0x02000000 // start of the flash memory | ||
65 | #define FW_VERSION *(unsigned short*)(FLASH_BASE + 0xFE) // firmware version | ||
66 | |||
67 | |||
68 | // prototypes | ||
69 | void _main(void) __attribute__ ((section (".startup"))); | ||
70 | int main(void); | ||
71 | void PlatformInit(void); | ||
72 | void DramInit(void); | ||
73 | int ucl_nrv2e_decompress_8(const UINT8 *src, UINT8 *dst, UINT32* dst_len); | ||
74 | void DecompressStart(tImage* pImage); | ||
75 | int ReadADC(int channel); | ||
76 | int ButtonPressed(void); | ||
77 | tImage* GetStartImage(int nPreferred); | ||
78 | // test functions | ||
79 | void SetLed(BOOL bOn); | ||
80 | void UartInit(void); | ||
81 | UINT8 UartRead(void); | ||
82 | void UartWrite(UINT8 byte); | ||
83 | void MiniMon(void); | ||
84 | |||
85 | |||
86 | // minimon commands | ||
87 | #define BAUDRATE 0x00 // followed by BRR value; response: command byte | ||
88 | #define ADDRESS 0x01 // followed by 4 bytes address; response: command byte | ||
89 | #define BYTE_READ 0x02 // response: 1 byte content | ||
90 | #define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte | ||
91 | #define BYTE_READ16 0x04 // response: 16 bytes content | ||
92 | #define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte | ||
93 | #define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte | ||
94 | #define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte | ||
95 | #define HALFWORD_READ 0x08 // response: 2 byte content | ||
96 | #define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte | ||
97 | #define EXECUTE 0x0A // response: command byte if call returns | ||
98 | #define VERSION 0x0B // response: version | ||
99 | |||
100 | |||
101 | // linker symbols | ||
102 | extern UINT32 begin_text[]; | ||
103 | extern UINT32 end_text[]; | ||
104 | extern UINT32 begin_data[]; | ||
105 | extern UINT32 end_data[]; | ||
106 | extern UINT32 begin_bss[]; | ||
107 | extern UINT32 end_bss[]; | ||
108 | extern UINT32 begin_stack[]; | ||
109 | extern UINT32 end_stack[]; | ||
110 | extern UINT32 begin_iramcopy[]; | ||
111 | extern UINT32 total_size[]; | ||
diff --git a/flash/bootloader/bootloader.lds b/flash/bootloader/bootloader.lds new file mode 100644 index 0000000000..143d83bdc7 --- /dev/null +++ b/flash/bootloader/bootloader.lds | |||
@@ -0,0 +1,34 @@ | |||
1 | OUTPUT_FORMAT(elf32-sh) | ||
2 | INPUT(bootloader.o) | ||
3 | |||
4 | MEMORY | ||
5 | { | ||
6 | /* the boot ROM uses IRAM at 400-430, stay away and start at 500 */ | ||
7 | IRAM : ORIGIN = 0x0FFFF500, LENGTH = 0xA00 | ||
8 | /* and leave some room for stack at the end */ | ||
9 | } | ||
10 | |||
11 | SECTIONS | ||
12 | { | ||
13 | .startvector : | ||
14 | { | ||
15 | *(.startvector) | ||
16 | . = ALIGN(0x4); | ||
17 | } > IRAM | ||
18 | |||
19 | .text : | ||
20 | { | ||
21 | *(.text) | ||
22 | . = ALIGN(0x4); | ||
23 | } > IRAM | ||
24 | |||
25 | .data : | ||
26 | { | ||
27 | *(.data) | ||
28 | } > IRAM | ||
29 | |||
30 | .bss : | ||
31 | { | ||
32 | *(.bss) | ||
33 | } > IRAM | ||
34 | } | ||
diff --git a/flash/bootloader/no_rom.lds b/flash/bootloader/no_rom.lds new file mode 100644 index 0000000000..e65e7fdd3c --- /dev/null +++ b/flash/bootloader/no_rom.lds | |||
@@ -0,0 +1,62 @@ | |||
1 | /* This is for the variant without boot ROM, | ||
2 | where the flash ROM is mirrored to address zero */ | ||
3 | |||
4 | OUTPUT_FORMAT(elf32-sh) | ||
5 | INPUT(bootloader.o) | ||
6 | |||
7 | MEMORY | ||
8 | { | ||
9 | IRAM : ORIGIN = 0x0FFFF000, LENGTH = 0x1000 | ||
10 | FLASH : ORIGIN = 0x00000000, LENGTH = 0x40000 | ||
11 | } | ||
12 | |||
13 | SECTIONS | ||
14 | { | ||
15 | .vectors : | ||
16 | { | ||
17 | *(.vectors) | ||
18 | . = ALIGN(0x200); | ||
19 | } > FLASH | ||
20 | |||
21 | .startup : | ||
22 | { | ||
23 | *(.startup) | ||
24 | . = ALIGN(0x4); | ||
25 | _begin_iramcopy = .; | ||
26 | } > FLASH | ||
27 | |||
28 | .text : AT ( _begin_iramcopy ) | ||
29 | { | ||
30 | _begin_text = .; | ||
31 | *(.text) | ||
32 | . = ALIGN(0x4); | ||
33 | _end_text = .; | ||
34 | } > IRAM | ||
35 | |||
36 | .data : AT ( _end_text ) | ||
37 | { | ||
38 | _begin_data = .; | ||
39 | *(.data) | ||
40 | . = ALIGN(0x4); | ||
41 | _end_data = .; | ||
42 | } > IRAM | ||
43 | |||
44 | .bss : AT ( _end_data ) | ||
45 | { | ||
46 | _begin_bss = .; | ||
47 | *(.bss) | ||
48 | . = ALIGN(0x4); | ||
49 | _end_bss = .; | ||
50 | } > IRAM | ||
51 | |||
52 | .stack : | ||
53 | { | ||
54 | _begin_stack = .; | ||
55 | *(.stack) | ||
56 | . = ALIGN(0x1000); | ||
57 | _end_stack = .; | ||
58 | } > IRAM | ||
59 | |||
60 | /* size of the program (without vectors) */ | ||
61 | _total_size = SIZEOF(.startup) + SIZEOF(.text) + SIZEOF(.data); | ||
62 | } | ||
diff --git a/flash/extract/README b/flash/extract/README new file mode 100644 index 0000000000..b66443aa34 --- /dev/null +++ b/flash/extract/README | |||
@@ -0,0 +1,5 @@ | |||
1 | (c) 2003 by Jörg Hohensohn | ||
2 | |||
3 | This tool extracts the firmware image out of an original Archos ROM dump, | ||
4 | like created with the Rockbox debug->dump feature. | ||
5 | The extracted image can then be used to compose a dual-boot firmware. | ||
diff --git a/flash/extract/extract.c b/flash/extract/extract.c new file mode 100644 index 0000000000..31e223a546 --- /dev/null +++ b/flash/extract/extract.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2003 by Jörg Hohensohn | ||
11 | * | ||
12 | * Tool to extract the scrambled image out of an Archos flash ROM dump | ||
13 | * | ||
14 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <memory.h> | ||
25 | |||
26 | #define UINT8 unsigned char | ||
27 | #define UINT16 unsigned short | ||
28 | #define UINT32 unsigned long | ||
29 | |||
30 | #define IMAGE_HEADER 0x6000 // a 32 byte header in front of the software image | ||
31 | #define IMAGE_START 0x6020 // software image position in Flash | ||
32 | |||
33 | |||
34 | // place a 32 bit value into memory, big endian | ||
35 | void Write32(UINT8* pByte, UINT32 value) | ||
36 | { | ||
37 | pByte[0] = (UINT8)(value >> 24); | ||
38 | pByte[1] = (UINT8)(value >> 16); | ||
39 | pByte[2] = (UINT8)(value >> 8); | ||
40 | pByte[3] = (UINT8)(value); | ||
41 | } | ||
42 | |||
43 | |||
44 | // read a 32 bit value from memory, big endian | ||
45 | UINT32 Read32(UINT8* pByte) | ||
46 | { | ||
47 | UINT32 value = 0; | ||
48 | |||
49 | value |= (UINT32)pByte[0] << 24; | ||
50 | value |= (UINT32)pByte[1] << 16; | ||
51 | value |= (UINT32)pByte[2] << 8; | ||
52 | value |= (UINT32)pByte[3]; | ||
53 | |||
54 | return value; | ||
55 | } | ||
56 | |||
57 | |||
58 | // entry point | ||
59 | int main(int argc, char* argv[]) | ||
60 | { | ||
61 | FILE* pInFile; | ||
62 | FILE* pOutFile; | ||
63 | UINT8 aHeader[6]; | ||
64 | UINT8 aImage[256*1024]; | ||
65 | UINT32 i; | ||
66 | UINT32 uiSize, uiStart; | ||
67 | UINT16 usChecksum = 0; | ||
68 | |||
69 | if (argc < 2) | ||
70 | { | ||
71 | printf("Extract the software image out of an original Archos Flash ROM dump.\n"); | ||
72 | printf("Result is a scrambled file, use the descramble tool to get the binary,\n"); | ||
73 | printf(" always without the -fm option, even if processing an FM software.\n\n"); | ||
74 | printf("Usage: extract <flash dump file> <output file>\n"); | ||
75 | printf("Example: extract internal_rom_2000000-203FFFF.bin archos.ajz\n"); | ||
76 | exit(0); | ||
77 | } | ||
78 | |||
79 | pInFile = fopen(argv[1], "rb"); | ||
80 | if (pInFile == NULL) | ||
81 | { | ||
82 | printf("Error opening input file %s\n", argv[1]); | ||
83 | exit(1); | ||
84 | } | ||
85 | |||
86 | if (fread(aImage, 1, sizeof(aImage), pInFile) != sizeof(aImage)) | ||
87 | { | ||
88 | printf("Error reading input file %s, must be 256kB in size.\n", argv[1]); | ||
89 | fclose(pInFile); | ||
90 | exit(2); | ||
91 | } | ||
92 | fclose(pInFile); | ||
93 | |||
94 | // find out about the type | ||
95 | uiStart = Read32(aImage + 8); | ||
96 | uiSize = Read32(aImage + 12); // booted ROM image | ||
97 | if (uiStart == 0x02000100 && uiSize > 20000) | ||
98 | { // Player has no loader, starts directly with the image | ||
99 | uiStart = 0x0100; | ||
100 | } | ||
101 | else | ||
102 | { // Recorder / FM / V2 Recorder | ||
103 | uiStart = IMAGE_START; | ||
104 | uiSize = Read32(aImage + IMAGE_HEADER + 4); // size record of header | ||
105 | } | ||
106 | |||
107 | // sanity check | ||
108 | if (uiSize > sizeof(aImage) - uiStart || uiSize < 40000) | ||
109 | { | ||
110 | printf("Error: Impossible image size &d bytes.\n", uiSize); | ||
111 | exit(3); | ||
112 | } | ||
113 | |||
114 | // generate checksum | ||
115 | for (i=0; i<uiSize; i++) | ||
116 | usChecksum += aImage[uiStart + i]; | ||
117 | |||
118 | // make header | ||
119 | Write32(aHeader + 2, usChecksum); // checksum in 5th and 6th byte | ||
120 | Write32(aHeader, uiSize); // size in first 4 bytes | ||
121 | |||
122 | pOutFile = fopen(argv[2], "wb"); | ||
123 | if (pOutFile == NULL) | ||
124 | { | ||
125 | printf("Error opening output file %s\n", argv[2]); | ||
126 | exit(4); | ||
127 | } | ||
128 | |||
129 | if (fwrite(aHeader, 1, sizeof(aHeader), pOutFile) != sizeof(aHeader) | ||
130 | || fwrite(aImage + uiStart, 1, uiSize, pOutFile) != uiSize) | ||
131 | { | ||
132 | printf("Write error\n"); | ||
133 | fclose(pOutFile); | ||
134 | exit(5); | ||
135 | } | ||
136 | |||
137 | fclose(pOutFile); | ||
138 | |||
139 | return 0; | ||
140 | } \ No newline at end of file | ||
diff --git a/flash/extract/extract.dsp b/flash/extract/extract.dsp new file mode 100644 index 0000000000..e10281a829 --- /dev/null +++ b/flash/extract/extract.dsp | |||
@@ -0,0 +1,100 @@ | |||
1 | # Microsoft Developer Studio Project File - Name="extract" - Package Owner=<4> | ||
2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 | ||
3 | # ** DO NOT EDIT ** | ||
4 | |||
5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 | ||
6 | |||
7 | CFG=extract - Win32 Debug | ||
8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, | ||
9 | !MESSAGE use the Export Makefile command and run | ||
10 | !MESSAGE | ||
11 | !MESSAGE NMAKE /f "extract.mak". | ||
12 | !MESSAGE | ||
13 | !MESSAGE You can specify a configuration when running NMAKE | ||
14 | !MESSAGE by defining the macro CFG on the command line. For example: | ||
15 | !MESSAGE | ||
16 | !MESSAGE NMAKE /f "extract.mak" CFG="extract - Win32 Debug" | ||
17 | !MESSAGE | ||
18 | !MESSAGE Possible choices for configuration are: | ||
19 | !MESSAGE | ||
20 | !MESSAGE "extract - Win32 Release" (based on "Win32 (x86) Console Application") | ||
21 | !MESSAGE "extract - Win32 Debug" (based on "Win32 (x86) Console Application") | ||
22 | !MESSAGE | ||
23 | |||
24 | # Begin Project | ||
25 | # PROP AllowPerConfigDependencies 0 | ||
26 | # PROP Scc_ProjName "" | ||
27 | # PROP Scc_LocalPath "" | ||
28 | CPP=cl.exe | ||
29 | RSC=rc.exe | ||
30 | |||
31 | !IF "$(CFG)" == "extract - Win32 Release" | ||
32 | |||
33 | # PROP BASE Use_MFC 0 | ||
34 | # PROP BASE Use_Debug_Libraries 0 | ||
35 | # PROP BASE Output_Dir "Release" | ||
36 | # PROP BASE Intermediate_Dir "Release" | ||
37 | # PROP BASE Target_Dir "" | ||
38 | # PROP Use_MFC 0 | ||
39 | # PROP Use_Debug_Libraries 0 | ||
40 | # PROP Output_Dir "Release" | ||
41 | # PROP Intermediate_Dir "Release" | ||
42 | # PROP Target_Dir "" | ||
43 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | ||
44 | # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c | ||
45 | # ADD BASE RSC /l 0x407 /d "NDEBUG" | ||
46 | # ADD RSC /l 0x407 /d "NDEBUG" | ||
47 | BSC32=bscmake.exe | ||
48 | # ADD BASE BSC32 /nologo | ||
49 | # ADD BSC32 /nologo | ||
50 | LINK32=link.exe | ||
51 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | ||
52 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | ||
53 | |||
54 | !ELSEIF "$(CFG)" == "extract - Win32 Debug" | ||
55 | |||
56 | # PROP BASE Use_MFC 0 | ||
57 | # PROP BASE Use_Debug_Libraries 1 | ||
58 | # PROP BASE Output_Dir "Debug" | ||
59 | # PROP BASE Intermediate_Dir "Debug" | ||
60 | # PROP BASE Target_Dir "" | ||
61 | # PROP Use_MFC 0 | ||
62 | # PROP Use_Debug_Libraries 1 | ||
63 | # PROP Output_Dir "Debug" | ||
64 | # PROP Intermediate_Dir "Debug" | ||
65 | # PROP Target_Dir "" | ||
66 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | ||
67 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c | ||
68 | # ADD BASE RSC /l 0x407 /d "_DEBUG" | ||
69 | # ADD RSC /l 0x407 /d "_DEBUG" | ||
70 | BSC32=bscmake.exe | ||
71 | # ADD BASE BSC32 /nologo | ||
72 | # ADD BSC32 /nologo | ||
73 | LINK32=link.exe | ||
74 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||
75 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||
76 | |||
77 | !ENDIF | ||
78 | |||
79 | # Begin Target | ||
80 | |||
81 | # Name "extract - Win32 Release" | ||
82 | # Name "extract - Win32 Debug" | ||
83 | # Begin Group "Source Files" | ||
84 | |||
85 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | ||
86 | # Begin Source File | ||
87 | |||
88 | SOURCE=.\extract.c | ||
89 | # End Source File | ||
90 | # End Group | ||
91 | # Begin Group "Header Files" | ||
92 | |||
93 | # PROP Default_Filter "h;hpp;hxx;hm;inl" | ||
94 | # End Group | ||
95 | # Begin Group "Resource Files" | ||
96 | |||
97 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" | ||
98 | # End Group | ||
99 | # End Target | ||
100 | # End Project | ||
diff --git a/flash/make_firmware/README b/flash/make_firmware/README new file mode 100644 index 0000000000..7110610284 --- /dev/null +++ b/flash/make_firmware/README | |||
@@ -0,0 +1,14 @@ | |||
1 | (c) 2003 by Jörg Hohensohn | ||
2 | |||
3 | This tool composes a firmware file, out of: | ||
4 | 1. Template for the first Flash page | ||
5 | 2. Bootloader | ||
6 | 3. Archos image | ||
7 | 4. Rockbox image | ||
8 | |||
9 | Use with extreme caution, the components have to match! | ||
10 | The aspects are: | ||
11 | - Model (Player, Recorder, FM, V2) | ||
12 | - boot type (standard boot ROM or ROMless) | ||
13 | |||
14 | Such a firmware file can then be programmed with "firmware_flash.rock". | ||
diff --git a/flash/make_firmware/make_firmware.c b/flash/make_firmware/make_firmware.c new file mode 100644 index 0000000000..220db4e5f1 --- /dev/null +++ b/flash/make_firmware/make_firmware.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2003 by Jörg Hohensohn | ||
11 | * | ||
12 | * Autoring tool for the firmware image to be programmed into Flash ROM | ||
13 | * It composes the flash content with header, bootloader and image(s) | ||
14 | * | ||
15 | * All files in this archive are subject to the GNU General Public License. | ||
16 | * See the file COPYING in the source tree root for full license agreement. | ||
17 | * | ||
18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
19 | * KIND, either express or implied. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | |||
24 | #include <stdio.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <memory.h> | ||
27 | #include <string.h> | ||
28 | |||
29 | #define UINT8 unsigned char | ||
30 | #define UINT16 unsigned short | ||
31 | #define UINT32 unsigned long | ||
32 | #define BOOL int | ||
33 | #define TRUE 1 | ||
34 | #define FALSE 0 | ||
35 | |||
36 | // size of one flash sector, the granularity with which it can be erased | ||
37 | #define SECTORSIZE 4096 | ||
38 | |||
39 | #define BOOTLOAD_DEST 0x0FFFF500 // for the "normal" one | ||
40 | #define BOOTLOAD_SCR 0x02000100 | ||
41 | #define ROCKBOX_DEST 0x09000000 | ||
42 | #define ROCKBOX_EXEC 0x09000200 | ||
43 | |||
44 | |||
45 | // place a 32 bit value into memory, big endian | ||
46 | void Write32(UINT8* pByte, UINT32 value) | ||
47 | { | ||
48 | pByte[0] = (UINT8)(value >> 24); | ||
49 | pByte[1] = (UINT8)(value >> 16); | ||
50 | pByte[2] = (UINT8)(value >> 8); | ||
51 | pByte[3] = (UINT8)(value); | ||
52 | } | ||
53 | |||
54 | |||
55 | // read a 32 bit value from memory, big endian | ||
56 | UINT32 Read32(UINT8* pByte) | ||
57 | { | ||
58 | UINT32 value = 0; | ||
59 | |||
60 | value |= (UINT32)pByte[0] << 24; | ||
61 | value |= (UINT32)pByte[1] << 16; | ||
62 | value |= (UINT32)pByte[2] << 8; | ||
63 | value |= (UINT32)pByte[3]; | ||
64 | |||
65 | return value; | ||
66 | } | ||
67 | |||
68 | |||
69 | UINT32 CalcCRC32 (const UINT8* buf, UINT32 len) | ||
70 | { | ||
71 | static const UINT32 crc_table[256] = | ||
72 | { // CRC32 lookup table for polynomial 0x04C11DB7 | ||
73 | 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, | ||
74 | 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, | ||
75 | 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, | ||
76 | 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, | ||
77 | 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, | ||
78 | 0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, | ||
79 | 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, | ||
80 | 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, | ||
81 | 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, | ||
82 | 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, | ||
83 | 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, | ||
84 | 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, | ||
85 | 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, | ||
86 | 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, | ||
87 | 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, | ||
88 | 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, | ||
89 | 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, | ||
90 | 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, | ||
91 | 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, | ||
92 | 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, | ||
93 | 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, | ||
94 | 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, | ||
95 | 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, | ||
96 | 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, | ||
97 | 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, | ||
98 | 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, | ||
99 | 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9, | ||
100 | 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, | ||
101 | 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, | ||
102 | 0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, | ||
103 | 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, | ||
104 | 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, | ||
105 | 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, | ||
106 | 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, | ||
107 | 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, | ||
108 | 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, | ||
109 | 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, | ||
110 | 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, | ||
111 | 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, | ||
112 | 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, | ||
113 | 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, | ||
114 | 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, | ||
115 | 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 | ||
116 | }; | ||
117 | UINT32 i; | ||
118 | UINT32 crc = 0xffffffff; | ||
119 | |||
120 | for (i = 0; i < len; i++) | ||
121 | crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *buf++) & 0xFF]; | ||
122 | |||
123 | return crc; | ||
124 | } | ||
125 | |||
126 | |||
127 | UINT32 PlaceImage(char* filename, UINT32 pos, UINT8* pFirmware, UINT32 limit) | ||
128 | { | ||
129 | UINT32 size, read; | ||
130 | FILE* pFile; | ||
131 | UINT32 align; | ||
132 | UINT32 flags; | ||
133 | |||
134 | // magic file header for compressed files | ||
135 | static const UINT8 magic[8] = { 0x00,0xe9,0x55,0x43,0x4c,0xff,0x01,0x1a }; | ||
136 | UINT8 ucl_header[26]; | ||
137 | |||
138 | pFile = fopen(filename, "rb"); // open the current image | ||
139 | if (pFile == NULL) | ||
140 | { | ||
141 | printf("Image file %s not found!\n", filename); | ||
142 | exit(5); | ||
143 | } | ||
144 | |||
145 | fseek(pFile, 0, SEEK_END); | ||
146 | size = ftell(pFile); | ||
147 | fseek(pFile, 0, SEEK_SET); | ||
148 | |||
149 | // determine if compressed | ||
150 | flags = 0x00000000; // default: flags for uncompressed | ||
151 | fread(ucl_header, 1, sizeof(ucl_header), pFile); | ||
152 | if (memcmp(magic, ucl_header, sizeof(magic)) == 0) | ||
153 | { | ||
154 | if (ucl_header[12] != 0x2E) // check algorithm | ||
155 | { | ||
156 | printf("UCL compressed files must use algorithm 2e, not %d\n", ucl_header[12]); | ||
157 | printf("Generate with: uclpack --best --2e rockbox.bin %s\n", filename); | ||
158 | exit(6); | ||
159 | } | ||
160 | |||
161 | size = Read32(ucl_header + 22); // compressed size | ||
162 | if (Read32(ucl_header + 18) > size) // compare with uncompressed size | ||
163 | { // normal case | ||
164 | flags = 0x00000001; // flags for UCL compressed | ||
165 | } | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | fseek(pFile, 0, SEEK_SET); // go back | ||
170 | } | ||
171 | |||
172 | if (pos + 16 + size > limit) // enough space for all that? | ||
173 | { | ||
174 | printf("Exceeding maximum image size %d\n", limit); | ||
175 | exit(7); | ||
176 | } | ||
177 | |||
178 | // write header | ||
179 | align = (pos + 16 + size + SECTORSIZE-1) & ~(SECTORSIZE-1); // round up to next flash sector | ||
180 | Write32(pFirmware + pos, ROCKBOX_DEST); // load address | ||
181 | Write32(pFirmware + pos + 4, align - (pos + 16)); // image size | ||
182 | Write32(pFirmware + pos + 8, ROCKBOX_EXEC); // execution address | ||
183 | Write32(pFirmware + pos + 12, flags); // compressed or not | ||
184 | pos += 16; | ||
185 | |||
186 | // load image | ||
187 | read = fread(pFirmware + pos, 1, size, pFile); | ||
188 | if (read != size) | ||
189 | { | ||
190 | printf("Read error, expecting %d bytes, got only %d\n", size, read); | ||
191 | exit(8); | ||
192 | } | ||
193 | fclose (pFile); | ||
194 | |||
195 | pos += size; | ||
196 | |||
197 | return pos; | ||
198 | } | ||
199 | |||
200 | |||
201 | int main(int argc, char* argv[]) | ||
202 | { | ||
203 | static UINT8 aFirmware[512*1024]; // maximum with exchanged chip | ||
204 | FILE* pFile; | ||
205 | UINT32 size; // size of loaded item | ||
206 | UINT32 pos; // current position in firmware | ||
207 | UINT32 crc32; // checksum of "payload" | ||
208 | BOOL hasBootRom; // flag if regular boot ROM or directly starts from flash | ||
209 | UINT32 template_F8, template_FC; // my platform ID, mask and version | ||
210 | |||
211 | int i; | ||
212 | |||
213 | if (argc <= 4) | ||
214 | { | ||
215 | printf("Usage:\n"); | ||
216 | printf("make_firmware <output> <template.bin> <bootloader.ajz> <image1.ucl> {image2.ucl}\n"); | ||
217 | printf("<template.bin> is the original firmware from your box\n"); | ||
218 | printf("<bootloader.ajz> is the scrambled bootloader\n"); | ||
219 | printf("<image1.ucl> is the first image, compressed (recommended) or uncompressed\n"); | ||
220 | printf("<image1.ucl> is the second image, compressed (recommended) or uncompressed\n"); | ||
221 | printf("More images may follow, but keep the flash size in mind!\n"); | ||
222 | printf("Compression must be UCL, algorithm 2e.\n"); | ||
223 | printf("Generated with: uclpack --best --2e rockbox.bin imageN.ucl\n"); | ||
224 | exit(0); | ||
225 | } | ||
226 | |||
227 | memset(aFirmware, 0xFF, sizeof(aFirmware)); | ||
228 | |||
229 | /******* process template *******/ | ||
230 | |||
231 | pFile = fopen(argv[2], "rb"); // open the template | ||
232 | if (pFile == NULL) | ||
233 | { | ||
234 | printf("Template file %s not found!\n", argv[2]); | ||
235 | exit(1); | ||
236 | } | ||
237 | size = fread(aFirmware, 1, 256, pFile); // need only the header | ||
238 | fclose(pFile); | ||
239 | if (size < 256) // need at least the firmware header | ||
240 | { | ||
241 | printf("Template file %s too small, need at least the header!\n", argv[2]); | ||
242 | exit(2); | ||
243 | } | ||
244 | |||
245 | if (strncmp(aFirmware, "ARCH", 4) == 0) | ||
246 | { | ||
247 | hasBootRom = TRUE; | ||
248 | pos = 256; // place bootloader after this "boot block" | ||
249 | } | ||
250 | else if (Read32(aFirmware) == 0x0200) | ||
251 | { | ||
252 | hasBootRom = FALSE; | ||
253 | pos = 0; // directly start with the bootloader | ||
254 | template_F8 = Read32(aFirmware + 0xF8); // my platform ID and future info | ||
255 | template_FC = Read32(aFirmware + 0xFC); // use mask+version from template | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | printf("Template file %s invalid!\n", argv[2]); | ||
260 | exit(3); | ||
261 | } | ||
262 | |||
263 | /******* process bootloader *******/ | ||
264 | |||
265 | pFile = fopen(argv[3], "rb"); // open the bootloader | ||
266 | if (pFile == NULL) | ||
267 | { | ||
268 | printf("Bootloader file %s not found!\n", argv[3]); | ||
269 | exit(4); | ||
270 | } | ||
271 | if (hasBootRom && fseek(pFile, 6, SEEK_SET)) // skip the ajz header | ||
272 | { | ||
273 | printf("Bootloader file %s too short!\n", argv[3]); | ||
274 | exit(5); | ||
275 | } | ||
276 | |||
277 | // place bootloader after header | ||
278 | size = fread(aFirmware + pos, 1, sizeof(aFirmware) - pos, pFile); | ||
279 | fclose(pFile); | ||
280 | |||
281 | if (hasBootRom) | ||
282 | { | ||
283 | Write32(aFirmware + 4, BOOTLOAD_DEST); // boot code destination address | ||
284 | |||
285 | for (i=0x08; i<=0x28; i+=8) | ||
286 | { | ||
287 | Write32(aFirmware + i, BOOTLOAD_SCR); // boot code source address | ||
288 | Write32(aFirmware + i + 4, size); // boot code size | ||
289 | } | ||
290 | } | ||
291 | else | ||
292 | { | ||
293 | Write32(aFirmware + 0xF8, template_F8); // values from template | ||
294 | Write32(aFirmware + 0xFC, template_FC); // mask and version | ||
295 | } | ||
296 | |||
297 | size = (size + 3) & ~3; // make shure it's 32 bit aligned | ||
298 | pos += size; // prepare position for first image | ||
299 | |||
300 | /******* process images *******/ | ||
301 | for (i = 4; i < argc; i++) | ||
302 | { | ||
303 | pos = PlaceImage(argv[i], pos, aFirmware, sizeof(aFirmware)); | ||
304 | |||
305 | if (i < argc-1) | ||
306 | { // not the last: round up to next flash sector | ||
307 | pos = (pos + SECTORSIZE-1) & ~(SECTORSIZE-1); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | |||
312 | /******* append CRC32 checksum *******/ | ||
313 | crc32 = CalcCRC32(aFirmware, pos); | ||
314 | Write32(aFirmware + pos, crc32); | ||
315 | pos += sizeof(crc32); // 4 bytes | ||
316 | |||
317 | |||
318 | /******* save result to output file *******/ | ||
319 | |||
320 | pFile = fopen(argv[1], "wb"); // open the output file | ||
321 | if (pFile == NULL) | ||
322 | { | ||
323 | printf("Output file %s cannot be created!\n", argv[1]); | ||
324 | exit(9); | ||
325 | } | ||
326 | size = fwrite(aFirmware, 1, pos, pFile); | ||
327 | fclose(pFile); | ||
328 | |||
329 | if (size != pos) | ||
330 | { | ||
331 | printf("Error writing %d bytes to output file %s!\n", pos, argv[1]); | ||
332 | exit(10); | ||
333 | } | ||
334 | |||
335 | printf("Firmware file generated with %d bytes.\n", pos); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
diff --git a/flash/make_firmware/make_firmware.dsp b/flash/make_firmware/make_firmware.dsp new file mode 100644 index 0000000000..54a6f53671 --- /dev/null +++ b/flash/make_firmware/make_firmware.dsp | |||
@@ -0,0 +1,96 @@ | |||
1 | # Microsoft Developer Studio Project File - Name="make_firmware" - Package Owner=<4> | ||
2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 | ||
3 | # ** DO NOT EDIT ** | ||
4 | |||
5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 | ||
6 | |||
7 | CFG=make_firmware - Win32 Debug | ||
8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, | ||
9 | !MESSAGE use the Export Makefile command and run | ||
10 | !MESSAGE | ||
11 | !MESSAGE NMAKE /f "make_firmware.mak". | ||
12 | !MESSAGE | ||
13 | !MESSAGE You can specify a configuration when running NMAKE | ||
14 | !MESSAGE by defining the macro CFG on the command line. For example: | ||
15 | !MESSAGE | ||
16 | !MESSAGE NMAKE /f "make_firmware.mak" CFG="make_firmware - Win32 Debug" | ||
17 | !MESSAGE | ||
18 | !MESSAGE Possible choices for configuration are: | ||
19 | !MESSAGE | ||
20 | !MESSAGE "make_firmware - Win32 Release" (based on "Win32 (x86) Console Application") | ||
21 | !MESSAGE "make_firmware - Win32 Debug" (based on "Win32 (x86) Console Application") | ||
22 | !MESSAGE | ||
23 | |||
24 | # Begin Project | ||
25 | # PROP AllowPerConfigDependencies 0 | ||
26 | # PROP Scc_ProjName "" | ||
27 | # PROP Scc_LocalPath "" | ||
28 | CPP=cl.exe | ||
29 | RSC=rc.exe | ||
30 | |||
31 | !IF "$(CFG)" == "make_firmware - Win32 Release" | ||
32 | |||
33 | # PROP BASE Use_MFC 0 | ||
34 | # PROP BASE Use_Debug_Libraries 0 | ||
35 | # PROP BASE Output_Dir "Release" | ||
36 | # PROP BASE Intermediate_Dir "Release" | ||
37 | # PROP BASE Target_Dir "" | ||
38 | # PROP Use_MFC 0 | ||
39 | # PROP Use_Debug_Libraries 0 | ||
40 | # PROP Output_Dir "Release" | ||
41 | # PROP Intermediate_Dir "Release" | ||
42 | # PROP Target_Dir "" | ||
43 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c | ||
44 | # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX"stdafx.h" /FD /c | ||
45 | # ADD BASE RSC /l 0x407 /d "NDEBUG" | ||
46 | # ADD RSC /l 0x407 /d "NDEBUG" | ||
47 | BSC32=bscmake.exe | ||
48 | # ADD BASE BSC32 /nologo | ||
49 | # ADD BSC32 /nologo | ||
50 | LINK32=link.exe | ||
51 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | ||
52 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | ||
53 | |||
54 | !ELSEIF "$(CFG)" == "make_firmware - Win32 Debug" | ||
55 | |||
56 | # PROP BASE Use_MFC 0 | ||
57 | # PROP BASE Use_Debug_Libraries 1 | ||
58 | # PROP BASE Output_Dir "Debug" | ||
59 | # PROP BASE Intermediate_Dir "Debug" | ||
60 | # PROP BASE Target_Dir "" | ||
61 | # PROP Use_MFC 0 | ||
62 | # PROP Use_Debug_Libraries 1 | ||
63 | # PROP Output_Dir "Debug" | ||
64 | # PROP Intermediate_Dir "Debug" | ||
65 | # PROP Target_Dir "" | ||
66 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c | ||
67 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX"stdafx.h" /FD /GZ /c | ||
68 | # ADD BASE RSC /l 0x407 /d "_DEBUG" | ||
69 | # ADD RSC /l 0x407 /d "_DEBUG" | ||
70 | BSC32=bscmake.exe | ||
71 | # ADD BASE BSC32 /nologo | ||
72 | # ADD BSC32 /nologo | ||
73 | LINK32=link.exe | ||
74 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||
75 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||
76 | |||
77 | !ENDIF | ||
78 | |||
79 | # Begin Target | ||
80 | |||
81 | # Name "make_firmware - Win32 Release" | ||
82 | # Name "make_firmware - Win32 Debug" | ||
83 | # Begin Group "Source Files" | ||
84 | |||
85 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | ||
86 | # Begin Source File | ||
87 | |||
88 | SOURCE=.\make_firmware.c | ||
89 | # End Source File | ||
90 | # End Group | ||
91 | # Begin Group "Header Files" | ||
92 | |||
93 | # PROP Default_Filter "h;hpp;hxx;hm;inl" | ||
94 | # End Group | ||
95 | # End Target | ||
96 | # End Project | ||
diff --git a/flash/minimon/Makefile b/flash/minimon/Makefile new file mode 100644 index 0000000000..57ae13e940 --- /dev/null +++ b/flash/minimon/Makefile | |||
@@ -0,0 +1,53 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | CC = sh-elf-gcc | ||
11 | LD = sh-elf-ld | ||
12 | AR = sh-elf-ar | ||
13 | AS = sh-elf-as | ||
14 | OC = sh-elf-objcopy | ||
15 | |||
16 | FIRMWARE := ../../firmware | ||
17 | TOOLSDIR=../../tools | ||
18 | |||
19 | TARGET = minimon | ||
20 | LDS := $(TARGET).lds | ||
21 | |||
22 | INCLUDES= -I$(FIRMWARE)/export -I. -I$(OBJDIR) | ||
23 | OBJDIR := . | ||
24 | |||
25 | CFLAGS = -fpic -O -W -Wall -m1 -nostdlib -ffreestanding -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(DEFINES) | ||
26 | AFLAGS += -small -relax | ||
27 | |||
28 | |||
29 | ifdef DEBUG | ||
30 | DEFINES := -DDEBUG | ||
31 | CFLAGS += -g | ||
32 | endif | ||
33 | |||
34 | SRC := $(wildcard *.c) | ||
35 | |||
36 | OBJS := $(SRC:%.c=$(OBJDIR)/%.o) | ||
37 | |||
38 | LINKFILE = $(OBJDIR)/$(TARGET).lds | ||
39 | |||
40 | |||
41 | $(OBJDIR)/$(TARGET).bin : $(OBJDIR)/$(TARGET).elf | ||
42 | $(OC) -O binary $(OBJDIR)/$(TARGET).elf $(OBJDIR)/$(TARGET).bin | ||
43 | $(TOOLSDIR)/sh2d $(OBJDIR)/$(TARGET).bin -o 0900000 > $(OBJDIR)/$(TARGET).asm | ||
44 | |||
45 | $(OBJDIR)/$(TARGET).elf : $(OBJS) | ||
46 | $(CC) -Os -nostdlib -o $(OBJDIR)/$(TARGET).elf -L$(OBJDIR) -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/$(TARGET).map | ||
47 | |||
48 | |||
49 | clean: | ||
50 | -rm -f $(OBJS) $(OBJDIR)/$(TARGET).asm \ | ||
51 | $(OBJDIR)/$(TARGET).bin \ | ||
52 | $(OBJDIR)/$(TARGET).elf \ | ||
53 | $(OBJDIR)/$(TARGET).map | ||
diff --git a/flash/minimon/README b/flash/minimon/README new file mode 100644 index 0000000000..b80edd9689 --- /dev/null +++ b/flash/minimon/README | |||
@@ -0,0 +1,6 @@ | |||
1 | (c) 2003 by Jörg Hohensohn | ||
2 | |||
3 | MiniMon is the tiny but powerful-enough piece of code that can be loaded | ||
4 | with the UART boot mod. | ||
5 | It allows to read and write memory, flash program, execute code. | ||
6 | This is suitable to reflash the box, load Rockbox or the gdb stub, etc. | ||
diff --git a/flash/minimon/minimon.c b/flash/minimon/minimon.c new file mode 100644 index 0000000000..e7981f2d09 --- /dev/null +++ b/flash/minimon/minimon.c | |||
@@ -0,0 +1,156 @@ | |||
1 | // minimalistic monitor | ||
2 | // to be loaded with the UART boot feature | ||
3 | // capable of reading and writing bytes, commanded by UART | ||
4 | |||
5 | #include "sh7034.h" | ||
6 | #include "minimon.h" | ||
7 | |||
8 | // scalar types | ||
9 | typedef unsigned char UINT8; | ||
10 | typedef unsigned short UINT16; | ||
11 | typedef unsigned long UINT32; | ||
12 | |||
13 | typedef void(*tpFunc)(void); // type for exec | ||
14 | typedef int(*tpMain)(void); // type for start vector to main() | ||
15 | |||
16 | |||
17 | // prototypes | ||
18 | int main(void); | ||
19 | |||
20 | // our binary has to start with a vector to the entry point | ||
21 | tpMain start_vector[] __attribute__ ((section (".startvector"))) = {main}; | ||
22 | |||
23 | |||
24 | UINT8 uart_read(void) | ||
25 | { | ||
26 | UINT8 byte; | ||
27 | while (!(SSR1 & SCI_RDRF)); // wait for char to be available | ||
28 | byte = RDR1; | ||
29 | SSR1 &= ~SCI_RDRF; | ||
30 | return byte; | ||
31 | } | ||
32 | |||
33 | |||
34 | void uart_write(UINT8 byte) | ||
35 | { | ||
36 | while (!(SSR1 & SCI_TDRE)); // wait for transmit buffer empty | ||
37 | TDR1 = byte; | ||
38 | SSR1 &= ~SCI_TDRE; | ||
39 | } | ||
40 | |||
41 | |||
42 | int main(void) | ||
43 | { | ||
44 | UINT8 cmd; | ||
45 | UINT32 addr; | ||
46 | UINT32 size; | ||
47 | UINT32 content; | ||
48 | volatile UINT8* paddr = 0; | ||
49 | volatile UINT8* pflash; // flash base address | ||
50 | |||
51 | while (1) | ||
52 | { | ||
53 | cmd = uart_read(); | ||
54 | switch (cmd) | ||
55 | { | ||
56 | case BAUDRATE: | ||
57 | content = uart_read(); | ||
58 | uart_write(cmd); // acknowledge by returning the command value | ||
59 | while (!(SSR1 & SCI_TEND)); // wait for empty shift register, before changing baudrate | ||
60 | BRR1 = content; | ||
61 | break; | ||
62 | |||
63 | case ADDRESS: | ||
64 | addr = (uart_read() << 24) | (uart_read() << 16) | (uart_read() << 8) | uart_read(); | ||
65 | paddr = (UINT8*)addr; | ||
66 | pflash = (UINT8*)(addr & 0xFFF80000); // round down to 512k align | ||
67 | uart_write(cmd); // acknowledge by returning the command value | ||
68 | break; | ||
69 | |||
70 | case BYTE_READ: | ||
71 | content = *paddr++; | ||
72 | uart_write(content); // the content is the ack | ||
73 | break; | ||
74 | |||
75 | case BYTE_WRITE: | ||
76 | content = uart_read(); | ||
77 | *paddr++ = content; | ||
78 | uart_write(cmd); // acknowledge by returning the command value | ||
79 | break; | ||
80 | |||
81 | case BYTE_READ16: | ||
82 | size = 16; | ||
83 | while (size--) | ||
84 | { | ||
85 | content = *paddr++; | ||
86 | uart_write(content); // the content is the ack | ||
87 | } | ||
88 | break; | ||
89 | |||
90 | case BYTE_WRITE16: | ||
91 | size = 16; | ||
92 | while (size--) | ||
93 | { | ||
94 | content = uart_read(); | ||
95 | *paddr++ = content; | ||
96 | } | ||
97 | uart_write(cmd); // acknowledge by returning the command value | ||
98 | break; | ||
99 | |||
100 | case BYTE_FLASH: | ||
101 | content = uart_read(); | ||
102 | pflash[0x5555] = 0xAA; // set flash to command mode | ||
103 | pflash[0x2AAA] = 0x55; | ||
104 | pflash[0x5555] = 0xA0; // byte program command | ||
105 | *paddr++ = content; | ||
106 | uart_write(cmd); // acknowledge by returning the command value | ||
107 | break; | ||
108 | |||
109 | case BYTE_FLASH16: | ||
110 | size = 16; | ||
111 | while (size--) | ||
112 | { | ||
113 | content = uart_read(); | ||
114 | pflash[0x5555] = 0xAA; // set flash to command mode | ||
115 | pflash[0x2AAA] = 0x55; | ||
116 | pflash[0x5555] = 0xA0; // byte program command | ||
117 | *paddr++ = content; | ||
118 | } | ||
119 | uart_write(cmd); // acknowledge by returning the command value | ||
120 | break; | ||
121 | |||
122 | case HALFWORD_READ: | ||
123 | content = *(UINT16*)paddr; | ||
124 | paddr += 2; | ||
125 | uart_write(content >> 8); // highbyte | ||
126 | uart_write(content & 0xFF); // lowbyte | ||
127 | break; | ||
128 | |||
129 | case HALFWORD_WRITE: | ||
130 | content = uart_read() << 8 | uart_read(); | ||
131 | *(UINT16*)paddr = content; | ||
132 | paddr += 2; | ||
133 | uart_write(cmd); // acknowledge by returning the command value | ||
134 | break; | ||
135 | |||
136 | case EXECUTE: | ||
137 | { | ||
138 | tpFunc pFunc = (tpFunc)paddr; | ||
139 | pFunc(); | ||
140 | uart_write(cmd); // acknowledge by returning the command value | ||
141 | } | ||
142 | break; | ||
143 | |||
144 | |||
145 | default: | ||
146 | { | ||
147 | volatile UINT16* pPortB = (UINT16*)0x05FFFFC2; | ||
148 | *pPortB |= 1 << 6; // bit 6 is red LED on | ||
149 | uart_write(~cmd); // error acknowledge | ||
150 | } | ||
151 | |||
152 | } // case | ||
153 | } | ||
154 | |||
155 | return 0; | ||
156 | } | ||
diff --git a/flash/minimon/minimon.h b/flash/minimon/minimon.h new file mode 100644 index 0000000000..b6e9805ecf --- /dev/null +++ b/flash/minimon/minimon.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef _MINIMON_H | ||
2 | #define _MINIMON_H | ||
3 | |||
4 | |||
5 | // Commands | ||
6 | // all multibyte values (address, halfwords) are passed as big endian | ||
7 | // (most significant of the bytes first) | ||
8 | |||
9 | // set the address (all read/write commands will auto-increment it) | ||
10 | #define BAUDRATE 0x00 // followed by BRR value; response: command byte | ||
11 | #define ADDRESS 0x01 // followed by 4 bytes address; response: command byte | ||
12 | #define BYTE_READ 0x02 // response: 1 byte content | ||
13 | #define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte | ||
14 | #define BYTE_READ16 0x04 // response: 16 bytes content | ||
15 | #define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte | ||
16 | #define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte | ||
17 | #define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte | ||
18 | #define HALFWORD_READ 0x08 // response: 2 byte content | ||
19 | #define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte | ||
20 | #define EXECUTE 0x0A // response: command byte if call returns | ||
21 | #define VERSION 0x0B // response: version | ||
22 | |||
23 | |||
24 | #endif // _MINIMON_H | ||
diff --git a/flash/minimon/minimon.lds b/flash/minimon/minimon.lds new file mode 100644 index 0000000000..dbdbdc3faa --- /dev/null +++ b/flash/minimon/minimon.lds | |||
@@ -0,0 +1,60 @@ | |||
1 | OUTPUT_FORMAT(elf32-sh) | ||
2 | INPUT(minimon.o) | ||
3 | |||
4 | MEMORY | ||
5 | { | ||
6 | DRAM : ORIGIN = 0x09000000, LENGTH = 0x200000 | ||
7 | } | ||
8 | |||
9 | SECTIONS | ||
10 | { | ||
11 | .startvector : | ||
12 | { | ||
13 | *(.startvector) | ||
14 | . = ALIGN(0x4); | ||
15 | } > DRAM | ||
16 | |||
17 | .got : | ||
18 | { | ||
19 | *(.got) | ||
20 | } > DRAM | ||
21 | |||
22 | .got.plt : | ||
23 | { | ||
24 | *(.got.plt) | ||
25 | } > DRAM | ||
26 | |||
27 | .rela.got : | ||
28 | { | ||
29 | *(.rela.got) | ||
30 | } > DRAM | ||
31 | |||
32 | .text : | ||
33 | { | ||
34 | . = ALIGN(0x200); | ||
35 | *(.entry) | ||
36 | *(.text) | ||
37 | . = ALIGN(0x4); | ||
38 | } > DRAM | ||
39 | |||
40 | .data : | ||
41 | { | ||
42 | *(.data) | ||
43 | } > DRAM | ||
44 | |||
45 | .rodata : | ||
46 | { | ||
47 | *(.rodata) | ||
48 | . = ALIGN(0x4); | ||
49 | } > DRAM | ||
50 | |||
51 | .bss : | ||
52 | { | ||
53 | *(.bss) | ||
54 | } > DRAM | ||
55 | |||
56 | .stack : | ||
57 | { | ||
58 | *(.stack) | ||
59 | } > DRAM | ||
60 | } | ||
diff --git a/flash/uart_boot/README b/flash/uart_boot/README new file mode 100644 index 0000000000..edfa20c121 --- /dev/null +++ b/flash/uart_boot/README | |||
@@ -0,0 +1,8 @@ | |||
1 | (c) 2003 by Jörg Hohensohn | ||
2 | |||
3 | This is the client side for MiniMon, a command line program that communicates with it. | ||
4 | It can be used to reflash a box from ground up, load a program like gdb stub or Rockbox, | ||
5 | and other diagnostics. | ||
6 | |||
7 | Current implementation is for Windows, but with a different UART implementation | ||
8 | it should work for other platforms (Linux) as well. | ||
diff --git a/flash/uart_boot/client.c b/flash/uart_boot/client.c new file mode 100644 index 0000000000..a98edc60cb --- /dev/null +++ b/flash/uart_boot/client.c | |||
@@ -0,0 +1,738 @@ | |||
1 | // client.cpp : functions for monitor download and communication. | ||
2 | // | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | #include "scalar_types.h" // (U)INT8/16/32 | ||
7 | #include "Uart.h" // platform abstraction for UART | ||
8 | #include "minimon.h" // protocol of my little monitor | ||
9 | |||
10 | // do the baudrate configuration for the Player | ||
11 | int ConfigFirstlevelPlayer (tUartHandle serial_handle) | ||
12 | { | ||
13 | UINT32 result_nbr; | ||
14 | |||
15 | if(!UartConfig(serial_handle, 4800, eMARKPARITY, eTWOSTOPBITS, 8)) | ||
16 | { | ||
17 | UINT32 dwErr = GET_LAST_ERR(); | ||
18 | printf("Error %d setting up COM params for baudrate byte\n", dwErr); | ||
19 | exit(1); | ||
20 | } | ||
21 | |||
22 | // this will read as 0x19 when viewed with 2300 baud like the player does | ||
23 | result_nbr = UartWrite(serial_handle, (UINT8*)"\x86\xC0", 2); | ||
24 | if (result_nbr != 2) | ||
25 | { | ||
26 | UINT32 dwErr = GET_LAST_ERR(); | ||
27 | printf("Error %d setting up COM params for baudrate byte\n", dwErr); | ||
28 | } | ||
29 | |||
30 | SLEEP(100); // wait for the chars to be sent, is there a better way? | ||
31 | |||
32 | // the read 0x19 means 14423 baud with 12 MHz | ||
33 | if(!UartConfig(serial_handle, 14400, eNOPARITY, eONESTOPBIT, 8)) | ||
34 | { | ||
35 | printf("Error setting up COM params for 1st level loader\n"); | ||
36 | exit(1); | ||
37 | } | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | |||
43 | // do the baudrate configuration for the Recoder/FM | ||
44 | int ConfigFirstlevelRecorder (tUartHandle serial_handle) | ||
45 | { | ||
46 | UINT32 result_nbr; | ||
47 | |||
48 | if(!UartConfig(serial_handle, 4800, eNOPARITY, eTWOSTOPBITS, 8)) | ||
49 | { | ||
50 | UINT32 dwErr = GET_LAST_ERR(); | ||
51 | printf("Error %d setting up COM params for baudrate byte\n", dwErr); | ||
52 | exit(1); | ||
53 | } | ||
54 | |||
55 | // this will read as 0x08 when viewed with 2120 baud like the recorder does | ||
56 | result_nbr = UartWrite(serial_handle, (UINT8*)"\x00\x00", 2); | ||
57 | if(result_nbr != 2) | ||
58 | { | ||
59 | printf("Error transmitting baudrate byte\n"); | ||
60 | exit(1); | ||
61 | } | ||
62 | |||
63 | SLEEP(100); // wait for the chars to be sent, is there a better way? | ||
64 | |||
65 | // the read 0x08 means 38400 baud with 11.0592 MHz | ||
66 | if(!UartConfig(serial_handle, 38400, eNOPARITY, eONESTOPBIT, 8)) | ||
67 | { | ||
68 | UINT32 dwErr = GET_LAST_ERR(); | ||
69 | printf("Error %d setting up COM params for 1st level loader\n", dwErr); | ||
70 | exit(1); | ||
71 | } | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | |||
77 | // transfer a byte for the monitor download, with or without acknowledge | ||
78 | int DownloadByte(tUartHandle serial_handle, unsigned char byte, bool bAck) | ||
79 | { | ||
80 | unsigned char received; | ||
81 | bool bRecorder = true; // false for player | ||
82 | |||
83 | while (1) | ||
84 | { | ||
85 | UartWrite(serial_handle, &byte, 1); | ||
86 | if (bAck) | ||
87 | { | ||
88 | UartRead(serial_handle, &received, 1); | ||
89 | if (received == byte) | ||
90 | { | ||
91 | UartWrite(serial_handle, (UINT8*)"\x01", 1); // ack success | ||
92 | break; // exit the loop | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | printf("Error transmitting monitor byte 0x%02X, got 0x%0X\n", byte, received); | ||
97 | UartWrite(serial_handle, (UINT8*)"\x00", 1); // ack fail, try again | ||
98 | } | ||
99 | } | ||
100 | else | ||
101 | break; // no loop | ||
102 | } | ||
103 | return 1; | ||
104 | } | ||
105 | |||
106 | |||
107 | // download our little monitor, the box must have been just freshly switched on for this to work | ||
108 | int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename) | ||
109 | { | ||
110 | FILE* pFile; | ||
111 | size_t filesize; | ||
112 | UINT8 byte; | ||
113 | unsigned i; | ||
114 | |||
115 | // hard-coded parameters | ||
116 | bool bAck = true; // configure if acknowledged download (without useful for remote pin boot) | ||
117 | UINT32 TargetLoad = 0x0FFFF000; // target load address | ||
118 | |||
119 | pFile = fopen(szFilename, "rb"); | ||
120 | if (pFile == NULL) | ||
121 | { | ||
122 | printf("\nMonitor file %s not found, exiting\n", szFilename); | ||
123 | exit(1); | ||
124 | } | ||
125 | |||
126 | // determine file size | ||
127 | fseek(pFile, 0, SEEK_END); | ||
128 | filesize = ftell(pFile); | ||
129 | fseek(pFile, 0, SEEK_SET); | ||
130 | |||
131 | // This is _really_ tricky! The box expects a BRR value in a nonstandard baudrate, | ||
132 | // which a PC can't generate. I'm using a higher one with some wild settings | ||
133 | // to generate a pulse series that: | ||
134 | // 1) looks like a stable byte when sampled with the nonstandard baudrate | ||
135 | // 2) gives a BRR value to the box which results in a baudrate the PC can also use | ||
136 | if (bRecorder) | ||
137 | { | ||
138 | ConfigFirstlevelRecorder(serial_handle); | ||
139 | } | ||
140 | else | ||
141 | { | ||
142 | ConfigFirstlevelPlayer(serial_handle); | ||
143 | } | ||
144 | |||
145 | UartWrite(serial_handle, bAck ? (UINT8*)"\x01" : (UINT8*)"\x00", 1); // ACK mode | ||
146 | |||
147 | // transmit the size, little endian | ||
148 | DownloadByte(serial_handle, (UINT8)( filesize & 0xFF), bAck); | ||
149 | DownloadByte(serial_handle, (UINT8)((filesize>>8) & 0xFF), bAck); | ||
150 | DownloadByte(serial_handle, (UINT8)((filesize>>16) & 0xFF), bAck); | ||
151 | DownloadByte(serial_handle, (UINT8)((filesize>>24) & 0xFF), bAck); | ||
152 | |||
153 | // transmit the load address, little endian | ||
154 | DownloadByte(serial_handle, (UINT8)( TargetLoad & 0xFF), bAck); | ||
155 | DownloadByte(serial_handle, (UINT8)((TargetLoad>>8) & 0xFF), bAck); | ||
156 | DownloadByte(serial_handle, (UINT8)((TargetLoad>>16) & 0xFF), bAck); | ||
157 | DownloadByte(serial_handle, (UINT8)((TargetLoad>>24) & 0xFF), bAck); | ||
158 | |||
159 | // transmit the command byte | ||
160 | DownloadByte(serial_handle, 0xFF, bAck); // 0xFF means execute the transferred image | ||
161 | |||
162 | // transmit the image | ||
163 | for (i=0; i<filesize; i++) | ||
164 | { | ||
165 | fread(&byte, 1, 1, pFile); | ||
166 | DownloadByte(serial_handle, byte, bAck); | ||
167 | } | ||
168 | |||
169 | fclose (pFile); | ||
170 | |||
171 | // now the image should have been started, red LED off | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | |||
177 | // wait for a fixed string to be received (no foolproof algorithm, | ||
178 | // may overlook if the searched string contains repeatitions) | ||
179 | int WaitForString(tUartHandle serial_handle, char* pszWait) | ||
180 | { | ||
181 | int i = 0; | ||
182 | unsigned char received; | ||
183 | |||
184 | while(pszWait[i] != '\0') | ||
185 | { | ||
186 | UartRead(serial_handle, &received, 1); | ||
187 | |||
188 | printf("%c", received); // debug | ||
189 | |||
190 | if (received == pszWait[i]) | ||
191 | i++; // continue | ||
192 | else | ||
193 | i=0; // mismatch, start over | ||
194 | } | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | |||
199 | // send a sting and check the echo | ||
200 | int SendWithEcho(tUartHandle serial_handle, char* pszSend) | ||
201 | { | ||
202 | int i = 0; | ||
203 | unsigned char received; | ||
204 | |||
205 | while(pszSend[i] != '\0') | ||
206 | { | ||
207 | UartWrite(serial_handle, (unsigned char*)(pszSend + i), 1); // send char | ||
208 | do | ||
209 | { | ||
210 | UartRead(serial_handle, &received, 1); // receive echo | ||
211 | printf("%c", received); // debug | ||
212 | } | ||
213 | while (received != pszSend[i]); // should normally be equal | ||
214 | i++; // next char | ||
215 | } | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | |||
220 | // rarely used variant: download our monitor using the built-in Archos monitor | ||
221 | int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename) | ||
222 | { | ||
223 | FILE* pFile; | ||
224 | size_t filesize; | ||
225 | UINT8 byte; | ||
226 | UINT16 checksum = 0; | ||
227 | unsigned i; | ||
228 | |||
229 | // the onboard monitor uses 115200 baud | ||
230 | if(!UartConfig(serial_handle, 115200, eNOPARITY, eONESTOPBIT, 8)) | ||
231 | { | ||
232 | UINT32 dwErr = GET_LAST_ERR(); | ||
233 | printf("Error %d setting up COM params for baudrate %d\n", dwErr, 115200); | ||
234 | exit(1); | ||
235 | } | ||
236 | |||
237 | // wait for receiving "#SERIAL#" | ||
238 | WaitForString(serial_handle, "#SERIAL#"); | ||
239 | |||
240 | // send magic "SRL" command to get interactive mode | ||
241 | SendWithEcho(serial_handle, "SRL\r"); | ||
242 | |||
243 | // wait for menu completion: "ROOT>" at the end | ||
244 | WaitForString(serial_handle, "ROOT>"); | ||
245 | |||
246 | // send upload command "UP" | ||
247 | SendWithEcho(serial_handle, "UP\r"); | ||
248 | |||
249 | pFile = fopen(szFilename, "rb"); | ||
250 | if (pFile == NULL) | ||
251 | { | ||
252 | printf("\nMonitor file %s not found, exiting\n", szFilename); | ||
253 | exit(1); | ||
254 | } | ||
255 | |||
256 | // determine file size | ||
257 | fseek(pFile, 0, SEEK_END); | ||
258 | filesize = ftell(pFile); | ||
259 | fseek(pFile, 0, SEEK_SET); | ||
260 | |||
261 | // calculate checksum | ||
262 | for (i=0; i<filesize; i++) | ||
263 | { | ||
264 | fread(&byte, 1, 1, pFile); | ||
265 | checksum += byte; | ||
266 | } | ||
267 | fseek(pFile, 0, SEEK_SET); | ||
268 | |||
269 | // send header | ||
270 | |||
271 | // size as 32 bit little endian | ||
272 | byte = (UINT8)( filesize & 0xFF); | ||
273 | UartWrite(serial_handle, &byte, 1); | ||
274 | byte = (UINT8)((filesize>>8) & 0xFF); | ||
275 | UartWrite(serial_handle, &byte, 1); | ||
276 | byte = (UINT8)((filesize>>16) & 0xFF); | ||
277 | UartWrite(serial_handle, &byte, 1); | ||
278 | byte = (UINT8)((filesize>>24) & 0xFF); | ||
279 | UartWrite(serial_handle, &byte, 1); | ||
280 | |||
281 | // checksum as 16 bit little endian | ||
282 | byte = (UINT8)( checksum & 0xFF); | ||
283 | UartWrite(serial_handle, &byte, 1); | ||
284 | byte = (UINT8)((checksum>>8) & 0xFF); | ||
285 | UartWrite(serial_handle, &byte, 1); | ||
286 | |||
287 | UartWrite(serial_handle, (unsigned char*)"\x00", 1); // kind (3 means flash) | ||
288 | UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte | ||
289 | |||
290 | // wait for monitor to accept data | ||
291 | WaitForString(serial_handle, "#OKCTRL#"); | ||
292 | |||
293 | // transmit the image | ||
294 | for (i=0; i<filesize; i++) | ||
295 | { | ||
296 | fread(&byte, 1, 1, pFile); | ||
297 | UartWrite(serial_handle, &byte, 1); // payload | ||
298 | } | ||
299 | fclose (pFile); | ||
300 | |||
301 | UartWrite(serial_handle, (unsigned char*)"\x00", 1); // ignored byte | ||
302 | |||
303 | // wait for menu completion: "ROOT>" at the end | ||
304 | WaitForString(serial_handle, "ROOT>"); | ||
305 | |||
306 | // send start program command "SPRO" | ||
307 | SendWithEcho(serial_handle, "SPRO\r"); | ||
308 | |||
309 | SLEEP(100); // wait a little while for startup | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | |||
315 | /********** Target functions using the Monitor Protocol **********/ | ||
316 | |||
317 | // read a byte using the target monitor | ||
318 | UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr) | ||
319 | { | ||
320 | UINT8 send; | ||
321 | UINT8 received; | ||
322 | |||
323 | // send the address command | ||
324 | send = ADDRESS; | ||
325 | UartWrite(serial_handle, &send, 1); | ||
326 | |||
327 | // transmit the address, big endian | ||
328 | send = (UINT8)((addr>>24) & 0xFF); | ||
329 | UartWrite(serial_handle, &send, 1); | ||
330 | send = (UINT8)((addr>>16) & 0xFF); | ||
331 | UartWrite(serial_handle, &send, 1); | ||
332 | send = (UINT8)((addr>>8) & 0xFF); | ||
333 | UartWrite(serial_handle, &send, 1); | ||
334 | send = (UINT8)(addr & 0xFF); | ||
335 | UartWrite(serial_handle, &send, 1); | ||
336 | |||
337 | UartRead(serial_handle, &received, 1); // response | ||
338 | if (received != ADDRESS) | ||
339 | { | ||
340 | printf("Protocol error!\n"); | ||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | // send the read command | ||
345 | send = BYTE_READ; | ||
346 | UartWrite(serial_handle, &send, 1); | ||
347 | |||
348 | UartRead(serial_handle, &received, 1); // response | ||
349 | |||
350 | return received; | ||
351 | } | ||
352 | |||
353 | |||
354 | // write a byte using the target monitor | ||
355 | int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte) | ||
356 | { | ||
357 | UINT8 send; | ||
358 | UINT8 received; | ||
359 | |||
360 | // send the address command | ||
361 | send = ADDRESS; | ||
362 | UartWrite(serial_handle, &send, 1); | ||
363 | |||
364 | // transmit the address, big endian | ||
365 | send = (UINT8)((addr>>24) & 0xFF); | ||
366 | UartWrite(serial_handle, &send, 1); | ||
367 | send = (UINT8)((addr>>16) & 0xFF); | ||
368 | UartWrite(serial_handle, &send, 1); | ||
369 | send = (UINT8)((addr>>8) & 0xFF); | ||
370 | UartWrite(serial_handle, &send, 1); | ||
371 | send = (UINT8)(addr & 0xFF); | ||
372 | UartWrite(serial_handle, &send, 1); | ||
373 | |||
374 | UartRead(serial_handle, &received, 1); // response | ||
375 | if (received != ADDRESS) | ||
376 | { | ||
377 | printf("Protocol error, receiced 0x%02X!\n", received); | ||
378 | return 1; | ||
379 | } | ||
380 | |||
381 | // send the write command | ||
382 | send = BYTE_WRITE; | ||
383 | UartWrite(serial_handle, &send, 1); | ||
384 | |||
385 | // transmit the data | ||
386 | UartWrite(serial_handle, &byte, 1); | ||
387 | |||
388 | UartRead(serial_handle, &received, 1); // response | ||
389 | |||
390 | if (received != BYTE_WRITE) | ||
391 | { | ||
392 | printf("Protocol error!\n"); | ||
393 | return 1; | ||
394 | } | ||
395 | |||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | |||
400 | // read many bytes using the target monitor | ||
401 | int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer) | ||
402 | { | ||
403 | UINT8 send, received; | ||
404 | |||
405 | // send the address command | ||
406 | send = ADDRESS; | ||
407 | UartWrite(serial_handle, &send, 1); | ||
408 | |||
409 | // transmit the address, big endian | ||
410 | send = (UINT8)((addr>>24) & 0xFF); | ||
411 | UartWrite(serial_handle, &send, 1); | ||
412 | send = (UINT8)((addr>>16) & 0xFF); | ||
413 | UartWrite(serial_handle, &send, 1); | ||
414 | send = (UINT8)((addr>>8) & 0xFF); | ||
415 | UartWrite(serial_handle, &send, 1); | ||
416 | send = (UINT8)(addr & 0xFF); | ||
417 | UartWrite(serial_handle, &send, 1); | ||
418 | |||
419 | UartRead(serial_handle, &received, 1); // response | ||
420 | if (received != ADDRESS) | ||
421 | { | ||
422 | printf("Protocol error!\n"); | ||
423 | return 1; | ||
424 | } | ||
425 | |||
426 | while (size) | ||
427 | { | ||
428 | if (size >= 16) | ||
429 | { // we can use a "burst" command | ||
430 | send = BYTE_READ16; | ||
431 | UartWrite(serial_handle, &send, 1); // send the read command | ||
432 | UartRead(serial_handle, pBuffer, 16); // data response | ||
433 | pBuffer += 16; | ||
434 | size -= 16; | ||
435 | } | ||
436 | else | ||
437 | { // use single byte command | ||
438 | send = BYTE_READ; | ||
439 | UartWrite(serial_handle, &send, 1); // send the read command | ||
440 | UartRead(serial_handle, pBuffer++, 1); // data response | ||
441 | size--; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | |||
449 | // write many bytes using the target monitor | ||
450 | int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer) | ||
451 | { | ||
452 | UINT8 send, received; | ||
453 | |||
454 | // send the address command | ||
455 | send = ADDRESS; | ||
456 | UartWrite(serial_handle, &send, 1); | ||
457 | |||
458 | // transmit the address, big endian | ||
459 | send = (UINT8)((addr>>24) & 0xFF); | ||
460 | UartWrite(serial_handle, &send, 1); | ||
461 | send = (UINT8)((addr>>16) & 0xFF); | ||
462 | UartWrite(serial_handle, &send, 1); | ||
463 | send = (UINT8)((addr>>8) & 0xFF); | ||
464 | UartWrite(serial_handle, &send, 1); | ||
465 | send = (UINT8)(addr & 0xFF); | ||
466 | UartWrite(serial_handle, &send, 1); | ||
467 | |||
468 | UartRead(serial_handle, &received, 1); // response | ||
469 | if (received != ADDRESS) | ||
470 | { | ||
471 | printf("Protocol error!\n"); | ||
472 | return 1; | ||
473 | } | ||
474 | |||
475 | while (size) | ||
476 | { | ||
477 | if (size >= 16) | ||
478 | { // we can use a "burst" command | ||
479 | send = BYTE_WRITE16; | ||
480 | UartWrite(serial_handle, &send, 1); // send the write command | ||
481 | UartWrite(serial_handle, pBuffer, 16); // transmit the data | ||
482 | UartRead(serial_handle, &received, 1); // response | ||
483 | if (received != BYTE_WRITE16) | ||
484 | { | ||
485 | printf("Protocol error!\n"); | ||
486 | return 1; | ||
487 | } | ||
488 | pBuffer += 16; | ||
489 | size -= 16; | ||
490 | } | ||
491 | else | ||
492 | { // use single byte command | ||
493 | send = BYTE_WRITE; | ||
494 | UartWrite(serial_handle, &send, 1); // send the write command | ||
495 | UartWrite(serial_handle, pBuffer++, 1); // transmit the data | ||
496 | UartRead(serial_handle, &received, 1); // response | ||
497 | if (received != BYTE_WRITE) | ||
498 | { | ||
499 | printf("Protocol error!\n"); | ||
500 | return 1; | ||
501 | } | ||
502 | size--; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | |||
510 | // write many bytes using the target monitor | ||
511 | int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer) | ||
512 | { | ||
513 | UINT8 send, received; | ||
514 | |||
515 | // send the address command | ||
516 | send = ADDRESS; | ||
517 | UartWrite(serial_handle, &send, 1); | ||
518 | |||
519 | // transmit the address, big endian | ||
520 | send = (UINT8)((addr>>24) & 0xFF); | ||
521 | UartWrite(serial_handle, &send, 1); | ||
522 | send = (UINT8)((addr>>16) & 0xFF); | ||
523 | UartWrite(serial_handle, &send, 1); | ||
524 | send = (UINT8)((addr>>8) & 0xFF); | ||
525 | UartWrite(serial_handle, &send, 1); | ||
526 | send = (UINT8)(addr & 0xFF); | ||
527 | UartWrite(serial_handle, &send, 1); | ||
528 | |||
529 | UartRead(serial_handle, &received, 1); // response | ||
530 | if (received != ADDRESS) | ||
531 | { | ||
532 | printf("Protocol error!\n"); | ||
533 | return 1; | ||
534 | } | ||
535 | |||
536 | while (size) | ||
537 | { | ||
538 | if (size >= 16) | ||
539 | { // we can use a "burst" command | ||
540 | send = BYTE_FLASH16; | ||
541 | UartWrite(serial_handle, &send, 1); // send the write command | ||
542 | UartWrite(serial_handle, pBuffer, 16); // transmit the data | ||
543 | UartRead(serial_handle, &received, 1); // response | ||
544 | if (received != BYTE_FLASH16) | ||
545 | { | ||
546 | printf("Protocol error!\n"); | ||
547 | return 1; | ||
548 | } | ||
549 | pBuffer += 16; | ||
550 | size -= 16; | ||
551 | } | ||
552 | else | ||
553 | { // use single byte command | ||
554 | send = BYTE_FLASH; | ||
555 | UartWrite(serial_handle, &send, 1); // send the write command | ||
556 | UartWrite(serial_handle, pBuffer++, 1); // transmit the data | ||
557 | UartRead(serial_handle, &received, 1); // response | ||
558 | if (received != BYTE_FLASH) | ||
559 | { | ||
560 | printf("Protocol error!\n"); | ||
561 | return 1; | ||
562 | } | ||
563 | size--; | ||
564 | } | ||
565 | } | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | |||
571 | // read a 16bit halfword using the target monitor | ||
572 | UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr) | ||
573 | { | ||
574 | UINT8 send; | ||
575 | UINT8 received; | ||
576 | UINT16 halfword; | ||
577 | |||
578 | // send the address command | ||
579 | send = ADDRESS; | ||
580 | UartWrite(serial_handle, &send, 1); | ||
581 | |||
582 | // transmit the address, big endian | ||
583 | send = (UINT8)((addr>>24) & 0xFF); | ||
584 | UartWrite(serial_handle, &send, 1); | ||
585 | send = (UINT8)((addr>>16) & 0xFF); | ||
586 | UartWrite(serial_handle, &send, 1); | ||
587 | send = (UINT8)((addr>>8) & 0xFF); | ||
588 | UartWrite(serial_handle, &send, 1); | ||
589 | send = (UINT8)(addr & 0xFF); | ||
590 | UartWrite(serial_handle, &send, 1); | ||
591 | |||
592 | UartRead(serial_handle, &received, 1); // response | ||
593 | if (received != ADDRESS) | ||
594 | { | ||
595 | printf("Protocol error!\n"); | ||
596 | return 1; | ||
597 | } | ||
598 | |||
599 | // send the read command | ||
600 | send = HALFWORD_READ; | ||
601 | UartWrite(serial_handle, &send, 1); | ||
602 | |||
603 | UartRead(serial_handle, &received, 1); // response | ||
604 | halfword = received << 8; // highbyte | ||
605 | UartRead(serial_handle, &received, 1); | ||
606 | halfword |= received; // lowbyte | ||
607 | |||
608 | return halfword; | ||
609 | } | ||
610 | |||
611 | |||
612 | // write a 16bit halfword using the target monitor | ||
613 | int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword) | ||
614 | { | ||
615 | UINT8 send; | ||
616 | UINT8 received; | ||
617 | |||
618 | // send the address command | ||
619 | send = ADDRESS; | ||
620 | UartWrite(serial_handle, &send, 1); | ||
621 | |||
622 | // transmit the address, big endian | ||
623 | send = (UINT8)((addr>>24) & 0xFF); | ||
624 | UartWrite(serial_handle, &send, 1); | ||
625 | send = (UINT8)((addr>>16) & 0xFF); | ||
626 | UartWrite(serial_handle, &send, 1); | ||
627 | send = (UINT8)((addr>>8) & 0xFF); | ||
628 | UartWrite(serial_handle, &send, 1); | ||
629 | send = (UINT8)(addr & 0xFF); | ||
630 | UartWrite(serial_handle, &send, 1); | ||
631 | |||
632 | UartRead(serial_handle, &received, 1); // response | ||
633 | if (received != ADDRESS) | ||
634 | { | ||
635 | printf("Protocol error!\n"); | ||
636 | return 1; | ||
637 | } | ||
638 | |||
639 | // send the write command | ||
640 | send = HALFWORD_WRITE; | ||
641 | UartWrite(serial_handle, &send, 1); | ||
642 | |||
643 | // transmit the data | ||
644 | send = halfword >> 8; // highbyte | ||
645 | UartWrite(serial_handle, &send, 1); | ||
646 | send = halfword & 0xFF; // lowbyte | ||
647 | UartWrite(serial_handle, &send, 1); | ||
648 | |||
649 | UartRead(serial_handle, &received, 1); // response | ||
650 | |||
651 | if (received != HALFWORD_WRITE) | ||
652 | { | ||
653 | printf("Protocol error!\n"); | ||
654 | return 1; | ||
655 | } | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | |||
661 | // change baudrate using target monitor | ||
662 | int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate) | ||
663 | { | ||
664 | UINT8 send; | ||
665 | UINT8 received; | ||
666 | UINT8 brr; | ||
667 | long lBRR; | ||
668 | |||
669 | lBRR = lClock / lBaudrate; | ||
670 | lBRR = ((lBRR + 16) / 32) - 1; // with rounding | ||
671 | brr = (UINT8)lBRR; | ||
672 | |||
673 | // send the command | ||
674 | send = BAUDRATE; | ||
675 | UartWrite(serial_handle, &send, 1); | ||
676 | UartWrite(serial_handle, &brr, 1); // send the BRR value | ||
677 | UartRead(serial_handle, &received, 1); // response ack | ||
678 | |||
679 | if (received != BAUDRATE) | ||
680 | { // bad situation, now we're unclear about the baudrate of the target | ||
681 | printf("Protocol error!\n"); | ||
682 | return 1; | ||
683 | } | ||
684 | |||
685 | SLEEP(100); // give it some time to settle | ||
686 | |||
687 | // change our baudrate, too | ||
688 | UartConfig(serial_handle, lBaudrate, eNOPARITY, eONESTOPBIT, 8); | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | |||
694 | // call a subroutine using the target monitor | ||
695 | int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns) | ||
696 | { | ||
697 | UINT8 send; | ||
698 | UINT8 received; | ||
699 | |||
700 | // send the address command | ||
701 | send = ADDRESS; | ||
702 | UartWrite(serial_handle, &send, 1); | ||
703 | |||
704 | // transmit the address, big endian | ||
705 | send = (UINT8)((addr>>24) & 0xFF); | ||
706 | UartWrite(serial_handle, &send, 1); | ||
707 | send = (UINT8)((addr>>16) & 0xFF); | ||
708 | UartWrite(serial_handle, &send, 1); | ||
709 | send = (UINT8)((addr>>8) & 0xFF); | ||
710 | UartWrite(serial_handle, &send, 1); | ||
711 | send = (UINT8)(addr & 0xFF); | ||
712 | UartWrite(serial_handle, &send, 1); | ||
713 | |||
714 | UartRead(serial_handle, &received, 1); // response | ||
715 | if (received != ADDRESS) | ||
716 | { | ||
717 | printf("Protocol error!\n"); | ||
718 | return 1; | ||
719 | } | ||
720 | |||
721 | // send the execute command | ||
722 | send = EXECUTE; | ||
723 | UartWrite(serial_handle, &send, 1); | ||
724 | if (bReturns) | ||
725 | { // we expect the call to return control to minimon | ||
726 | UartRead(serial_handle, &received, 1); // response | ||
727 | |||
728 | if (received != EXECUTE) | ||
729 | { | ||
730 | printf("Protocol error!\n"); | ||
731 | return 1; | ||
732 | } | ||
733 | } | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | |||
diff --git a/flash/uart_boot/client.h b/flash/uart_boot/client.h new file mode 100644 index 0000000000..d2ef29aa2e --- /dev/null +++ b/flash/uart_boot/client.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _CLIENT_H | ||
2 | #define _CLIENT_H | ||
3 | |||
4 | |||
5 | // setup function for monitor download | ||
6 | int DownloadMonitor(tUartHandle serial_handle, bool bRecorder, char* szFilename); | ||
7 | int DownloadArchosMonitor(tUartHandle serial_handle, char* szFilename); | ||
8 | |||
9 | // target functions using the Monitor Protocol | ||
10 | UINT8 ReadByte(tUartHandle serial_handle, UINT32 addr); | ||
11 | int WriteByte(tUartHandle serial_handle, UINT32 addr, UINT8 byte); | ||
12 | int ReadByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer); | ||
13 | int WriteByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer); | ||
14 | int FlashByteMultiple(tUartHandle serial_handle, UINT32 addr, UINT32 size, UINT8* pBuffer); | ||
15 | UINT16 ReadHalfword(tUartHandle serial_handle, UINT32 addr); | ||
16 | int WriteHalfword(tUartHandle serial_handle, UINT32 addr, UINT16 halfword); | ||
17 | int SetTargetBaudrate(tUartHandle serial_handle, long lClock, long lBaudrate); | ||
18 | int Execute(tUartHandle serial_handle, UINT32 addr, bool bReturns); | ||
19 | |||
20 | |||
21 | #endif \ No newline at end of file | ||
diff --git a/flash/uart_boot/flash.c b/flash/uart_boot/flash.c new file mode 100644 index 0000000000..f27bb7ec0a --- /dev/null +++ b/flash/uart_boot/flash.c | |||
@@ -0,0 +1,77 @@ | |||
1 | // flash.cpp : higher-level functions for flashing the chip | ||
2 | // | ||
3 | |||
4 | #include "scalar_types.h" // (U)INT8/16/32 | ||
5 | #include "Uart.h" // platform abstraction for UART | ||
6 | #include "client.h" // client functions | ||
7 | |||
8 | |||
9 | // read the manufacturer and device ID | ||
10 | int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID) | ||
11 | { | ||
12 | base &= 0xFFF80000; // round down to 512k align, to make shure | ||
13 | |||
14 | WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode | ||
15 | WriteByte(serial_handle, base + 0x2AAA, 0x55); | ||
16 | WriteByte(serial_handle, base + 0x5555, 0x90); // ID command | ||
17 | SLEEP(20); // Atmel wants 20ms pause here | ||
18 | |||
19 | *pManufacturerID = ReadByte(serial_handle, base + 0); | ||
20 | *pDeviceID = ReadByte(serial_handle, base + 1); | ||
21 | |||
22 | WriteByte(serial_handle, base + 0, 0xF0); // reset flash (back to normal read mode) | ||
23 | SLEEP(20); // Atmel wants 20ms pause here | ||
24 | |||
25 | return 0; | ||
26 | } | ||
27 | |||
28 | |||
29 | // erase the sector which contains the given address | ||
30 | int EraseSector(tUartHandle serial_handle, UINT32 address) | ||
31 | { | ||
32 | UINT32 base = address & 0xFFF80000; // round down to 512k align | ||
33 | |||
34 | WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode | ||
35 | WriteByte(serial_handle, base + 0x2AAA, 0x55); | ||
36 | WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command | ||
37 | WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode | ||
38 | WriteByte(serial_handle, base + 0x2AAA, 0x55); | ||
39 | WriteByte(serial_handle, address, 0x30); // eraze the sector | ||
40 | SLEEP(25); // sector eraze time: 25ms | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | |||
46 | // erase the whole flash | ||
47 | int EraseChip(tUartHandle serial_handle, UINT32 base) | ||
48 | { | ||
49 | base &= 0xFFF80000; // round down to 512k align, to make shure | ||
50 | |||
51 | WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode | ||
52 | WriteByte(serial_handle, base + 0x2AAA, 0x55); | ||
53 | WriteByte(serial_handle, base + 0x5555, 0x80); // eraze command | ||
54 | WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode | ||
55 | WriteByte(serial_handle, base + 0x2AAA, 0x55); | ||
56 | WriteByte(serial_handle, base + 0x5555, 0x10); // chip eraze command | ||
57 | SLEEP(100); // chip eraze time: 100ms | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | |||
63 | // program a bunch of bytes "by hand" | ||
64 | int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size) | ||
65 | { | ||
66 | UINT32 base = address & 0xFFF80000; // round down to 512k align | ||
67 | |||
68 | while (size--) | ||
69 | { | ||
70 | WriteByte(serial_handle, base + 0x5555, 0xAA); // enter command mode | ||
71 | WriteByte(serial_handle, base + 0x2AAA, 0x55); | ||
72 | WriteByte(serial_handle, base + 0x5555, 0xA0); // byte program command | ||
73 | WriteByte(serial_handle, address++, *pData++); | ||
74 | // UART protocol is slow enough such that I don't have to wait 20us here | ||
75 | } | ||
76 | return 0; | ||
77 | } \ No newline at end of file | ||
diff --git a/flash/uart_boot/flash.h b/flash/uart_boot/flash.h new file mode 100644 index 0000000000..70c620108d --- /dev/null +++ b/flash/uart_boot/flash.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _FLASH_H | ||
2 | #define _FLASH_H | ||
3 | |||
4 | int ReadID(tUartHandle serial_handle, UINT32 base, UINT8* pManufacturerID, UINT8* pDeviceID); | ||
5 | int EraseSector(tUartHandle serial_handle, UINT32 address); | ||
6 | int EraseChip(tUartHandle serial_handle, UINT32 base); | ||
7 | int ProgramBytes(tUartHandle serial_handle, UINT32 address, UINT8* pData, UINT32 size); | ||
8 | |||
9 | #endif \ No newline at end of file | ||
diff --git a/flash/uart_boot/minimon.h b/flash/uart_boot/minimon.h new file mode 100644 index 0000000000..51406d4b12 --- /dev/null +++ b/flash/uart_boot/minimon.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef _MINIMON_H | ||
2 | #define _MINIMON_H | ||
3 | |||
4 | |||
5 | // Commands | ||
6 | // all multibyte values (address, halfwords) are passed as big endian | ||
7 | // (most significant of the bytes first) | ||
8 | |||
9 | // set the address (all read/write commands will auto-increment it) | ||
10 | #define BAUDRATE 0x00 // followed by BRR value; response: command byte | ||
11 | #define ADDRESS 0x01 // followed by 4 bytes address; response: command byte | ||
12 | #define BYTE_READ 0x02 // response: 1 byte content | ||
13 | #define BYTE_WRITE 0x03 // followed by 1 byte content; response: command byte | ||
14 | #define BYTE_READ16 0x04 // response: 16 bytes content | ||
15 | #define BYTE_WRITE16 0x05 // followed by 16 bytes; response: command byte | ||
16 | #define BYTE_FLASH 0x06 // followed by 1 byte content; response: command byte | ||
17 | #define BYTE_FLASH16 0x07 // followed by 16 bytes; response: command byte | ||
18 | #define HALFWORD_READ 0x08 // response: 2 byte content | ||
19 | #define HALFWORD_WRITE 0x09 // followed by 2 byte content; response: command byte | ||
20 | #define EXECUTE 0x0A // response: command byte if call returns | ||
21 | |||
22 | |||
23 | #endif // _MINIMON_H | ||
diff --git a/flash/uart_boot/scalar_types.h b/flash/uart_boot/scalar_types.h new file mode 100644 index 0000000000..88d82c4ec1 --- /dev/null +++ b/flash/uart_boot/scalar_types.h | |||
@@ -0,0 +1,44 @@ | |||
1 | // this is meant to resolve platform dependency | ||
2 | |||
3 | #ifndef _SCALAR_TYPES_H | ||
4 | #define _SCALAR_TYPES_H | ||
5 | |||
6 | |||
7 | #ifdef WIN32 | ||
8 | #include <windows.h> | ||
9 | #define SLEEP Sleep | ||
10 | #define GET_LAST_ERR GetLastError | ||
11 | #endif | ||
12 | // ToDo: add stuff for Linux | ||
13 | |||
14 | |||
15 | |||
16 | #ifndef UINT8 | ||
17 | #define UINT8 unsigned char | ||
18 | #endif | ||
19 | |||
20 | #ifndef UINT16 | ||
21 | #define UINT16 unsigned short | ||
22 | #endif | ||
23 | |||
24 | #ifndef UINT32 | ||
25 | #define UINT32 unsigned long | ||
26 | #endif | ||
27 | |||
28 | #ifndef bool | ||
29 | #define bool int | ||
30 | #endif | ||
31 | |||
32 | #ifndef true | ||
33 | #define true 1 | ||
34 | #endif | ||
35 | |||
36 | #ifndef false | ||
37 | #define false 0 | ||
38 | #endif | ||
39 | |||
40 | |||
41 | |||
42 | |||
43 | |||
44 | #endif \ No newline at end of file | ||
diff --git a/flash/uart_boot/uart.h b/flash/uart_boot/uart.h new file mode 100644 index 0000000000..46b082c497 --- /dev/null +++ b/flash/uart_boot/uart.h | |||
@@ -0,0 +1,56 @@ | |||
1 | // A general definition for the required UART functionality. | ||
2 | // This will be used to gain platform abstraction. | ||
3 | |||
4 | #ifndef _UART_H | ||
5 | #define _UART_H | ||
6 | |||
7 | // data types | ||
8 | |||
9 | typedef void* tUartHandle; | ||
10 | #define INVALID_UART_HANDLE (tUartHandle)-1 | ||
11 | |||
12 | typedef enum | ||
13 | { | ||
14 | eNOPARITY, | ||
15 | eODDPARITY, | ||
16 | eEVENPARITY, | ||
17 | eMARKPARITY, | ||
18 | eSPACEPARITY, | ||
19 | } tParity; | ||
20 | |||
21 | typedef enum | ||
22 | { | ||
23 | eONESTOPBIT, | ||
24 | eONE5STOPBITS, | ||
25 | eTWOSTOPBITS, | ||
26 | } tStopBits; | ||
27 | |||
28 | |||
29 | // prototypes | ||
30 | |||
31 | tUartHandle UartOpen( // returns NULL on error | ||
32 | char* szPortName); // COMx for windows | ||
33 | |||
34 | bool UartConfig( // returns true on success, false on error | ||
35 | tUartHandle handle, // the handle returned from UartOpen() | ||
36 | long lBaudRate, // must be one of the "standard" baudrates | ||
37 | tParity nParity, // what kind of parity | ||
38 | tStopBits nStopBits, // how many stop bits | ||
39 | int nByteSize); // size of the "payload", can be 5 to 8 | ||
40 | |||
41 | long UartWrite( // returns how much data was actually transmitted | ||
42 | tUartHandle handle, // the handle returned from UartOpen() | ||
43 | unsigned char* pData, // pointer to the data to be transmitted | ||
44 | long lSize); // how many bytes | ||
45 | |||
46 | long UartRead( // returns how much data was actually received | ||
47 | tUartHandle handle, // the handle returned from UartOpen() | ||
48 | unsigned char* pBuffer, // pointer to the destination | ||
49 | long lSize); // how many bytes to read (pBuffer must have enough room) | ||
50 | |||
51 | |||
52 | void UartClose(tUartHandle handle); | ||
53 | |||
54 | |||
55 | |||
56 | #endif // _UART_H \ No newline at end of file | ||
diff --git a/flash/uart_boot/uart_boot.c b/flash/uart_boot/uart_boot.c new file mode 100644 index 0000000000..8110e9b678 --- /dev/null +++ b/flash/uart_boot/uart_boot.c | |||
@@ -0,0 +1,337 @@ | |||
1 | // uart_boot.cpp : Defines the entry point for the console application. | ||
2 | // | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <string.h> | ||
7 | #include "scalar_types.h" // (U)INT8/16/32 | ||
8 | #include "Uart.h" // platform abstraction for UART | ||
9 | #include "client.h" // client functions | ||
10 | #include "flash.h" // flash high level functions | ||
11 | |||
12 | // command line configuration: what shall we do? | ||
13 | struct | ||
14 | { | ||
15 | char* szPort; // COM port to use | ||
16 | bool bRecorder; // it's a recorder | ||
17 | bool bArchos; // use the Archos monitor to load, instead of UART boot | ||
18 | bool bSpindown; // spindown the harddisk | ||
19 | bool bReadID; // read manufacturer+device ID | ||
20 | char* szFlashfile; // file to be programmed | ||
21 | char* szDumpfile; // file to dump into | ||
22 | char* szExecfile; // file with the executable | ||
23 | bool bTest; // debug action | ||
24 | bool bBlink; // blink red LED | ||
25 | bool bNoDownload; | ||
26 | } gCmd; | ||
27 | |||
28 | |||
29 | int ProcessCmdLine(int argc, char* argv[]) | ||
30 | { | ||
31 | argc--; // exclude our name | ||
32 | argv++; | ||
33 | |||
34 | memset(&gCmd, 0, sizeof(gCmd)); | ||
35 | |||
36 | if (argc == 0) | ||
37 | { | ||
38 | printf("Usage: uart_boot [-option {filename}]\n"); | ||
39 | printf(" uses activated UART boot mod, box has to be fresh started\n"); | ||
40 | printf("The order of the options does not matter, one letter is sufficient.\n"); | ||
41 | printf("Possible options are (in the order of later processing):\n"); | ||
42 | printf("-port <name of COM port to use>\n"); | ||
43 | printf("-recorder (this is a recorder/FM, default is player if not specified)\n"); | ||
44 | printf("-archos (use Archos bootloader, this one needs powerup while program waits)\n"); | ||
45 | printf("-nodownload (no MiniMon download, it's already active)\n"); | ||
46 | printf("-spindown (spindown the harddisk, else it stays on by default)\n"); | ||
47 | printf("-id (read manufacturer and device ID of flash, no checks)\n"); | ||
48 | printf("-flash <filename of binary to program into flash>\n"); | ||
49 | printf("-dump <filename to write flash content to>\n"); | ||
50 | printf("-exec <filename of executable for 0x09000000:0x09000200>\n"); | ||
51 | printf("-test (some test action currently under development, don't use!)\n"); | ||
52 | printf("-blink (blink red LED forever, meant as diagnostics)\n"); | ||
53 | printf("\n"); | ||
54 | printf("Examples:\n"); | ||
55 | printf("uart_boot -r -p COM1 -s -f flashfile.bin -d dumpfile.bin\n"); | ||
56 | printf(" recorder on COM1, spindown HD, program and dump (for e.g. offline verify)\n"); | ||
57 | printf("uart_boot -r -p COM2 -e rockbox.bin\n"); | ||
58 | printf(" recorder on COM2, load Rockbox from file and start it\n"); | ||
59 | exit (0); | ||
60 | } | ||
61 | |||
62 | |||
63 | while (argc) | ||
64 | { | ||
65 | if (!strncmp("-port", *argv, 2)) | ||
66 | { | ||
67 | gCmd.szPort = *++argv; | ||
68 | if (--argc <= 0 || **argv == '-') | ||
69 | { | ||
70 | printf("No argument given for option %s, aborting.\n", argv[-1]); | ||
71 | exit (-2); | ||
72 | } | ||
73 | } | ||
74 | else if (!strncmp("-recorder", *argv, 2)) | ||
75 | { | ||
76 | gCmd.bRecorder = true; | ||
77 | } | ||
78 | else if (!strncmp("-archos", *argv, 2)) | ||
79 | { | ||
80 | gCmd.bArchos = true; | ||
81 | } | ||
82 | else if (!strncmp("-nodownload", *argv, 2)) | ||
83 | { | ||
84 | gCmd.bNoDownload = true; | ||
85 | } | ||
86 | else if (!strncmp("-spindown", *argv, 2)) | ||
87 | { | ||
88 | gCmd.bSpindown = true; | ||
89 | } | ||
90 | else if (!strncmp("-id", *argv, 2)) | ||
91 | { | ||
92 | gCmd.bReadID = true; | ||
93 | } | ||
94 | else if (!strncmp("-flash", *argv, 2)) | ||
95 | { | ||
96 | gCmd.szFlashfile = *++argv; | ||
97 | if (--argc <= 0 || **argv == '-') | ||
98 | { | ||
99 | printf("No argument given for option %s, aborting.\n", argv[-1]); | ||
100 | exit (-2); | ||
101 | } | ||
102 | } | ||
103 | else if (!strncmp("-dump", *argv, 2)) | ||
104 | { | ||
105 | gCmd.szDumpfile = *++argv; | ||
106 | if (--argc <= 0 || **argv == '-') | ||
107 | { | ||
108 | printf("No argument given for option %s, aborting.\n", argv[-1]); | ||
109 | exit (-3); | ||
110 | } | ||
111 | } | ||
112 | else if (!strncmp("-exec", *argv, 2)) | ||
113 | { | ||
114 | gCmd.szExecfile = *++argv; | ||
115 | if (--argc <= 0 || **argv == '-') | ||
116 | { | ||
117 | printf("No argument given for option %s, aborting.\n", argv[-1]); | ||
118 | exit (-4); | ||
119 | } | ||
120 | } | ||
121 | else if (!strncmp("-test", *argv, 2)) | ||
122 | { | ||
123 | gCmd.bTest = true; | ||
124 | } | ||
125 | else if (!strncmp("-blink", *argv, 2)) | ||
126 | { | ||
127 | gCmd.bBlink = true; | ||
128 | } | ||
129 | else | ||
130 | { | ||
131 | printf("Unknown option %s, aborting. Use 'uart_boot' without options for help.\n", *argv); | ||
132 | exit(-1); | ||
133 | } | ||
134 | |||
135 | argv++; | ||
136 | argc--; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | |||
143 | int main(int argc, char* argv[]) | ||
144 | { | ||
145 | tUartHandle serial_handle; | ||
146 | UINT16 reg; | ||
147 | FILE* pFile; | ||
148 | size_t size; | ||
149 | UINT8 abFirmware[512*1024]; // blocksize | ||
150 | memset(abFirmware, 0xFF, sizeof(abFirmware)); | ||
151 | |||
152 | ProcessCmdLine(argc, argv); // what to do | ||
153 | |||
154 | if (!gCmd.szPort) | ||
155 | { | ||
156 | printf("No serial port given, use 'uart_boot' without parameters for options.\n"); | ||
157 | exit(-1); | ||
158 | } | ||
159 | |||
160 | serial_handle = UartOpen(gCmd.szPort); // opening serial port | ||
161 | if (serial_handle == NULL) | ||
162 | { | ||
163 | printf("Cannot open port %s\n", gCmd.szPort); | ||
164 | return -1; | ||
165 | } | ||
166 | |||
167 | if (gCmd.bNoDownload) | ||
168 | { // just set our speed | ||
169 | if (!UartConfig(serial_handle, gCmd.bRecorder ? 115200 : 14400, eNOPARITY, eONESTOPBIT, 8)) | ||
170 | { | ||
171 | printf("Error setting up COM params\n"); | ||
172 | exit(1); | ||
173 | } | ||
174 | } | ||
175 | else | ||
176 | { // download the monitor program | ||
177 | if (gCmd.bArchos) | ||
178 | { | ||
179 | printf("Waiting for box startup to download monitor..."); | ||
180 | DownloadArchosMonitor(serial_handle, "minimon_v2.bin"); // load the monitor image | ||
181 | printf("\b\b\b done.\n"); | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | printf("Downloading monitor..."); | ||
186 | DownloadMonitor(serial_handle, gCmd.bRecorder, "minimon.bin"); // load the monitor image | ||
187 | // From now on, we can talk to the box. | ||
188 | printf("\b\b\b done.\n"); | ||
189 | |||
190 | if (gCmd.bRecorder) | ||
191 | { // we can be faster | ||
192 | SetTargetBaudrate(serial_handle, 11059200, 115200); // set to 115200 | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | |||
197 | // do the action | ||
198 | |||
199 | if (gCmd.bSpindown) | ||
200 | { | ||
201 | // spindown the disk (works only for master) | ||
202 | UINT32 ata; // address of ATA_ALT_STATUS | ||
203 | printf("Harddisk spindown..."); | ||
204 | ata = (gCmd.bRecorder && (ReadHalfword(serial_handle, 0x020000FC) & 0x0100)) ? 0x06200206 : 0x06200306; | ||
205 | WriteHalfword(serial_handle, 0x05FFFFCA, 0xBF99); // PACR2 (was 0xFF99) | ||
206 | WriteHalfword(serial_handle, 0x05FFFFC4, 0x0280); // PAIOR (was 0x0000) | ||
207 | WriteHalfword(serial_handle, 0x05FFFFC0, 0xA27F); // PADR (was 0xA0FF) | ||
208 | while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY | ||
209 | WriteByte(serial_handle, 0x06100107, 0xE0); // ATA_COMMAND = CMD_STANDBY_IMMEDIATE; | ||
210 | //while (ReadByte(serial_handle, ata) & 0x80); // ATA_ALT_STATUS & STATUS_BSY | ||
211 | printf("\b\b\b done.\n"); | ||
212 | } | ||
213 | |||
214 | |||
215 | if (gCmd.bReadID) | ||
216 | { | ||
217 | UINT8 bMan, bID; | ||
218 | ReadID(serial_handle, 0x02000000, &bMan, &bID); | ||
219 | printf("Manufacturer ID = 0x%02X, Device ID = 0x%02X\n", bMan, bID); | ||
220 | } | ||
221 | |||
222 | |||
223 | if (gCmd.szFlashfile) | ||
224 | { | ||
225 | // flash a firmware file | ||
226 | printf("Flashing file %s...", gCmd.szFlashfile); | ||
227 | pFile = fopen(gCmd.szFlashfile, "rb"); | ||
228 | if (pFile == NULL) | ||
229 | { | ||
230 | printf("\nFlash file %s not found, exiting.\n", gCmd.szFlashfile); | ||
231 | return -2; | ||
232 | } | ||
233 | size = fread(abFirmware, 1, sizeof(abFirmware), pFile); | ||
234 | fclose (pFile); | ||
235 | |||
236 | EraseChip(serial_handle, 0x02000000); | ||
237 | FlashByteMultiple(serial_handle, 0x02000000, size, abFirmware); | ||
238 | printf("\b\b\b done.\n"); | ||
239 | } | ||
240 | |||
241 | |||
242 | if (gCmd.szDumpfile) | ||
243 | { | ||
244 | // dump the flash content | ||
245 | printf("Writing flash dump into file %s...", gCmd.szDumpfile); | ||
246 | ReadByteMultiple(serial_handle, 0x02000000, sizeof(abFirmware), abFirmware); | ||
247 | pFile = fopen(gCmd.szDumpfile, "wb"); | ||
248 | if (pFile == NULL) | ||
249 | { | ||
250 | printf("\nDump file %s cannot be opened, exiting.\n", gCmd.szDumpfile); | ||
251 | return -3; | ||
252 | } | ||
253 | fwrite(abFirmware, 1, sizeof(abFirmware), pFile); | ||
254 | fclose (pFile); | ||
255 | printf("\b\b\b done.\n"); | ||
256 | } | ||
257 | |||
258 | |||
259 | if (gCmd.szExecfile) | ||
260 | { | ||
261 | UINT32 size; | ||
262 | |||
263 | printf("Downloading program..."); | ||
264 | |||
265 | // init the DRAM controller like the flash boot does | ||
266 | reg = ReadHalfword(serial_handle, 0x05FFFFCA); // PACR2 | ||
267 | reg &= 0xFFFB; // PA1 config: /RAS | ||
268 | reg |= 0x0008; | ||
269 | WriteHalfword(serial_handle, 0x05FFFFCA, reg); // PACR2 | ||
270 | reg = 0xAFFF; // CS1, CS3 config: /CASH. /CASL | ||
271 | WriteHalfword(serial_handle, 0x05FFFFEE, reg); // CASCR | ||
272 | reg = ReadHalfword(serial_handle, 0x05FFFFA0); // BCR | ||
273 | reg |= 0x8000; // DRAM enable, default bus | ||
274 | WriteHalfword(serial_handle, 0x05FFFFA0, reg); // BCR | ||
275 | reg = ReadHalfword(serial_handle, 0x05FFFFA2); // WCR1 | ||
276 | reg &= 0xFDFD; // 1-cycle CAS | ||
277 | WriteHalfword(serial_handle, 0x05FFFFA2, reg); // WCR1 | ||
278 | reg = 0x0E00; // CAS 35%, multiplexed, 10 bit row addr. | ||
279 | WriteHalfword(serial_handle, 0x05FFFFA8, reg); // DCR | ||
280 | reg = 0x5AB0; // refresh, 4 cycle waitstate | ||
281 | WriteHalfword(serial_handle, 0x05FFFFAC, reg); // RCR | ||
282 | reg = 0x9605; // refresh constant | ||
283 | WriteHalfword(serial_handle, 0x05FFFFB2, reg); // RTCOR | ||
284 | reg = 0xA518; // phi/32 | ||
285 | WriteHalfword(serial_handle, 0x05FFFFAE, reg); // RTCSR | ||
286 | |||
287 | |||
288 | // download Rockbox/gdb | ||
289 | pFile = fopen(gCmd.szExecfile, "rb"); | ||
290 | if (pFile == NULL) | ||
291 | { | ||
292 | printf("\nExecutable file %s cannot be opened, exiting.\n", gCmd.szExecfile); | ||
293 | return -3; | ||
294 | } | ||
295 | |||
296 | size = fread(abFirmware, 1, sizeof(abFirmware), pFile); | ||
297 | WriteByteMultiple(serial_handle, 0x09000000, size, abFirmware); | ||
298 | fclose (pFile); | ||
299 | printf("\b\b\b done.\n"); | ||
300 | |||
301 | // start rockbox/gdb | ||
302 | printf("Starting program..."); | ||
303 | Execute(serial_handle, 0x09000200, false); | ||
304 | printf("\b\b\b done.\n"); | ||
305 | } | ||
306 | |||
307 | |||
308 | if (gCmd.bTest) | ||
309 | { | ||
310 | // test code: query keypad | ||
311 | while (1) | ||
312 | { | ||
313 | WriteByte(serial_handle, 0x05FFFEE8, 0x24); // ADCSR | ||
314 | while (!(ReadByte(serial_handle, 0x05FFFEE8) & 0x80)); | ||
315 | reg = ReadHalfword(serial_handle, 0x05FFFEE0); // ADDRA | ||
316 | printf("ADC(4): %d\n", reg>>6); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | |||
321 | if (gCmd.bBlink) | ||
322 | { | ||
323 | // blinking LED | ||
324 | UINT8 byte; | ||
325 | printf("Flashing red LED forever... (stop with Ctrl-C)\n"); | ||
326 | byte = ReadByte(serial_handle, 0x05FFFFC3); | ||
327 | while (1) | ||
328 | { | ||
329 | byte ^= 0x40; | ||
330 | WriteByte(serial_handle, 0x05FFFFC3, byte); | ||
331 | Sleep(200); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
diff --git a/flash/uart_boot/uart_boot.dsp b/flash/uart_boot/uart_boot.dsp new file mode 100644 index 0000000000..4d94c72530 --- /dev/null +++ b/flash/uart_boot/uart_boot.dsp | |||
@@ -0,0 +1,130 @@ | |||
1 | # Microsoft Developer Studio Project File - Name="uart_boot" - Package Owner=<4> | ||
2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 | ||
3 | # ** DO NOT EDIT ** | ||
4 | |||
5 | # TARGTYPE "Win32 (x86) Console Application" 0x0103 | ||
6 | |||
7 | CFG=uart_boot - Win32 Debug | ||
8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, | ||
9 | !MESSAGE use the Export Makefile command and run | ||
10 | !MESSAGE | ||
11 | !MESSAGE NMAKE /f "uart_boot.mak". | ||
12 | !MESSAGE | ||
13 | !MESSAGE You can specify a configuration when running NMAKE | ||
14 | !MESSAGE by defining the macro CFG on the command line. For example: | ||
15 | !MESSAGE | ||
16 | !MESSAGE NMAKE /f "uart_boot.mak" CFG="uart_boot - Win32 Debug" | ||
17 | !MESSAGE | ||
18 | !MESSAGE Possible choices for configuration are: | ||
19 | !MESSAGE | ||
20 | !MESSAGE "uart_boot - Win32 Release" (based on "Win32 (x86) Console Application") | ||
21 | !MESSAGE "uart_boot - Win32 Debug" (based on "Win32 (x86) Console Application") | ||
22 | !MESSAGE | ||
23 | |||
24 | # Begin Project | ||
25 | # PROP AllowPerConfigDependencies 0 | ||
26 | # PROP Scc_ProjName "" | ||
27 | # PROP Scc_LocalPath "" | ||
28 | CPP=cl.exe | ||
29 | RSC=rc.exe | ||
30 | |||
31 | !IF "$(CFG)" == "uart_boot - Win32 Release" | ||
32 | |||
33 | # PROP BASE Use_MFC 0 | ||
34 | # PROP BASE Use_Debug_Libraries 0 | ||
35 | # PROP BASE Output_Dir "Release" | ||
36 | # PROP BASE Intermediate_Dir "Release" | ||
37 | # PROP BASE Target_Dir "" | ||
38 | # PROP Use_MFC 0 | ||
39 | # PROP Use_Debug_Libraries 0 | ||
40 | # PROP Output_Dir "Release" | ||
41 | # PROP Intermediate_Dir "Release" | ||
42 | # PROP Target_Dir "" | ||
43 | # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c | ||
44 | # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /c | ||
45 | # SUBTRACT CPP /YX /Yc /Yu | ||
46 | # ADD BASE RSC /l 0x407 /d "NDEBUG" | ||
47 | # ADD RSC /l 0x407 /d "NDEBUG" | ||
48 | BSC32=bscmake.exe | ||
49 | # ADD BASE BSC32 /nologo | ||
50 | # ADD BSC32 /nologo | ||
51 | LINK32=link.exe | ||
52 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | ||
53 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 | ||
54 | |||
55 | !ELSEIF "$(CFG)" == "uart_boot - Win32 Debug" | ||
56 | |||
57 | # PROP BASE Use_MFC 0 | ||
58 | # PROP BASE Use_Debug_Libraries 1 | ||
59 | # PROP BASE Output_Dir "Debug" | ||
60 | # PROP BASE Intermediate_Dir "Debug" | ||
61 | # PROP BASE Target_Dir "" | ||
62 | # PROP Use_MFC 0 | ||
63 | # PROP Use_Debug_Libraries 1 | ||
64 | # PROP Output_Dir "Debug" | ||
65 | # PROP Intermediate_Dir "Debug" | ||
66 | # PROP Target_Dir "" | ||
67 | # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c | ||
68 | # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c | ||
69 | # SUBTRACT CPP /YX /Yc /Yu | ||
70 | # ADD BASE RSC /l 0x407 /d "_DEBUG" | ||
71 | # ADD RSC /l 0x407 /d "_DEBUG" | ||
72 | BSC32=bscmake.exe | ||
73 | # ADD BASE BSC32 /nologo | ||
74 | # ADD BSC32 /nologo | ||
75 | LINK32=link.exe | ||
76 | # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||
77 | # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept | ||
78 | |||
79 | !ENDIF | ||
80 | |||
81 | # Begin Target | ||
82 | |||
83 | # Name "uart_boot - Win32 Release" | ||
84 | # Name "uart_boot - Win32 Debug" | ||
85 | # Begin Group "Source Files" | ||
86 | |||
87 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" | ||
88 | # Begin Source File | ||
89 | |||
90 | SOURCE=.\client.c | ||
91 | # End Source File | ||
92 | # Begin Source File | ||
93 | |||
94 | SOURCE=.\flash.c | ||
95 | # End Source File | ||
96 | # Begin Source File | ||
97 | |||
98 | SOURCE=.\uart_boot.c | ||
99 | # End Source File | ||
100 | # Begin Source File | ||
101 | |||
102 | SOURCE=.\uart_win.c | ||
103 | # End Source File | ||
104 | # End Group | ||
105 | # Begin Group "Header Files" | ||
106 | |||
107 | # PROP Default_Filter "h;hpp;hxx;hm;inl" | ||
108 | # Begin Source File | ||
109 | |||
110 | SOURCE=.\client.h | ||
111 | # End Source File | ||
112 | # Begin Source File | ||
113 | |||
114 | SOURCE=.\flash.h | ||
115 | # End Source File | ||
116 | # Begin Source File | ||
117 | |||
118 | SOURCE=.\minimon.h | ||
119 | # End Source File | ||
120 | # Begin Source File | ||
121 | |||
122 | SOURCE=.\scalar_types.h | ||
123 | # End Source File | ||
124 | # Begin Source File | ||
125 | |||
126 | SOURCE=.\uart.h | ||
127 | # End Source File | ||
128 | # End Group | ||
129 | # End Target | ||
130 | # End Project | ||
diff --git a/flash/uart_boot/uart_win.c b/flash/uart_boot/uart_win.c new file mode 100644 index 0000000000..243017ac88 --- /dev/null +++ b/flash/uart_boot/uart_win.c | |||
@@ -0,0 +1,138 @@ | |||
1 | // UART wrapper implementation for the Win32 platform | ||
2 | // make a new version of this file for different systems, e.g. Linux | ||
3 | |||
4 | #include <windows.h> | ||
5 | #include "scalar_types.h" // (U)INT8/16/32 | ||
6 | #include "Uart.h" | ||
7 | |||
8 | // COMx for windows, returns NULL on error | ||
9 | tUartHandle UartOpen(char* szPortName) | ||
10 | { | ||
11 | HANDLE serial_handle; | ||
12 | DCB dcb; | ||
13 | COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 }; | ||
14 | |||
15 | memset(&dcb,0,sizeof(dcb)); | ||
16 | |||
17 | /* -------------------------------------------------------------------- */ | ||
18 | // set DCB to configure the serial port | ||
19 | dcb.DCBlength = sizeof(dcb); | ||
20 | |||
21 | dcb.fOutxCtsFlow = 0; | ||
22 | dcb.fOutxDsrFlow = 0; | ||
23 | dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable for power | ||
24 | dcb.fDsrSensitivity = 0; | ||
25 | dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable for power | ||
26 | dcb.fOutX = 0; | ||
27 | dcb.fInX = 0; | ||
28 | |||
29 | /* ----------------- misc parameters ----- */ | ||
30 | dcb.fErrorChar = 0; | ||
31 | dcb.fBinary = 1; | ||
32 | dcb.fNull = 0; | ||
33 | dcb.fAbortOnError = 0; | ||
34 | dcb.wReserved = 0; | ||
35 | dcb.XonLim = 2; | ||
36 | dcb.XoffLim = 4; | ||
37 | dcb.XonChar = 0x13; | ||
38 | dcb.XoffChar = 0x19; | ||
39 | dcb.EvtChar = 0; | ||
40 | |||
41 | /* ----------------- defaults ----- */ | ||
42 | dcb.BaudRate = 4800; | ||
43 | dcb.Parity = NOPARITY; | ||
44 | dcb.fParity = 0; | ||
45 | dcb.StopBits = ONESTOPBIT; | ||
46 | dcb.ByteSize = 8; | ||
47 | |||
48 | |||
49 | /* -------------------------------------------------------------------- */ | ||
50 | // opening serial port | ||
51 | serial_handle = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE, | ||
52 | 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); | ||
53 | |||
54 | if (serial_handle == INVALID_HANDLE_VALUE) | ||
55 | { | ||
56 | //printf("Cannot open port \n"); | ||
57 | return NULL; | ||
58 | } | ||
59 | |||
60 | SetCommMask(serial_handle, 0); | ||
61 | SetCommTimeouts(serial_handle, &cto); | ||
62 | |||
63 | if(!SetCommState(serial_handle, &dcb)) | ||
64 | { | ||
65 | //printf("Error setting up COM params\n"); | ||
66 | CloseHandle(serial_handle); | ||
67 | return NULL; | ||
68 | } | ||
69 | |||
70 | return serial_handle; | ||
71 | } | ||
72 | |||
73 | // returns true on success, false on error | ||
74 | bool UartConfig(tUartHandle handle, long lBaudRate, tParity nParity, tStopBits nStopBits, int nByteSize) | ||
75 | { | ||
76 | DCB dcb; | ||
77 | |||
78 | if (!GetCommState (handle, &dcb)) | ||
79 | { | ||
80 | return false; | ||
81 | } | ||
82 | |||
83 | dcb.BaudRate = lBaudRate; | ||
84 | dcb.Parity = nParity; | ||
85 | dcb.StopBits = nStopBits; | ||
86 | dcb.ByteSize = nByteSize; | ||
87 | |||
88 | if(!SetCommState(handle, &dcb)) | ||
89 | { | ||
90 | //DWORD dwErr = GetLastError(); | ||
91 | //printf("Error %d setting up COM params for baudrate byte\n", dwErr); | ||
92 | return false; | ||
93 | } | ||
94 | |||
95 | return true; | ||
96 | } | ||
97 | |||
98 | // returns how much data was actually transmitted | ||
99 | long UartWrite(tUartHandle handle, unsigned char* pData, long lSize) | ||
100 | { | ||
101 | BOOL success; | ||
102 | DWORD result_nbr; | ||
103 | |||
104 | success = WriteFile(handle, pData, lSize, &result_nbr, NULL); | ||
105 | |||
106 | if(!success) | ||
107 | { | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | return result_nbr; | ||
112 | } | ||
113 | |||
114 | // returns how much data was actually received | ||
115 | long UartRead(tUartHandle handle, unsigned char* pBuffer, long lSize) | ||
116 | { | ||
117 | BOOL success; | ||
118 | DWORD read_nbr; | ||
119 | |||
120 | success = ReadFile(handle, pBuffer, lSize, &read_nbr, NULL); | ||
121 | if(!success) | ||
122 | { | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | return read_nbr; | ||
127 | } | ||
128 | |||
129 | |||
130 | void UartClose(tUartHandle handle) | ||
131 | { | ||
132 | if (handle != NULL) | ||
133 | { | ||
134 | CloseHandle(handle); | ||
135 | } | ||
136 | |||
137 | return; | ||
138 | } | ||