source: trunk/platform/ixus220_elph300hs/sub/101g/boot.c @ 919

Revision 919, 17.9 KB checked in by rudi_de, 16 months ago (diff)

Aktualisierung auf Rev. 1547 und 1549 internationaler Branch: Release-1.0
http://trac.assembla.com/chdk/changeset/1547/branches/release-1_0
http://trac.assembla.com/chdk/changeset/1549/branches/release-1_0
Danke stefantalpalaru und msl!

Betrifft ixus220
+ Firmwareversion 101g hinzugefügt, Status: ALPHA

  • Property svn:eol-style set to native
Line 
1#include "lolevel.h"
2#include "platform.h"
3#include "core.h"
4#include "dryos31.h"
5
6#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
7
8const char * const new_sa = &_end;
9
10// Forward declarations
11void CreateTask_PhySw();
12void CreateTask_spytask();
13
14/* void __attribute__((naked,noinline)) my_blinker(int n) {
15        asm volatile (
16                                "STMFD   SP!, {R0-R5,LR}\n"
17        );
18       
19        int i, j;
20        for (j=0; j<n; j++)
21        {
22                *((volatile int *) 0xC0223030) = 0x46; // Turn on AF LED
23                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
24
25                *((volatile int *) 0xC0223030) = 0x44; // Turn off AF LED
26                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
27        }
28        for (i=0; i<0x900000; i++) { asm volatile ( "nop\n" ); }
29        asm volatile (
30                                "LDMFD   SP!, {R0-R5,PC}\n"
31        );
32}
33
34void __attribute__((naked,noinline)) my_blinker1(int n) {
35        asm volatile (
36                                "STMFD   SP!, {R0-R5,LR}\n"
37        );
38       
39        int i, j;
40        for (j=0; j<n; j++)
41        {
42                *((volatile int *) 0xC0220130) = 0x46; // Turn on Back LED
43                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
44
45                *((volatile int *) 0xC0220130) = 0x44; // Turn off Back LED
46                for (i=0; i<0x200000; i++) { asm volatile ( "nop\n" ); }
47        }
48        for (i=0; i<0x900000; i++) { asm volatile ( "nop\n" ); }
49        asm volatile (
50                                "LDMFD   SP!, {R0-R5,PC}\n"
51        );
52}
53 */
54
55extern void task_CaptSeq();
56extern void task_InitFileModules();
57extern void task_MovieRecord();
58extern void task_ExpDrv();
59
60void taskHook(context_t **context)
61{
62        task_t *tcb=(task_t*)((char*)context-offsetof(task_t, context));
63
64        // Replace firmware task addresses with ours
65        if(tcb->entry == (void*)task_CaptSeq)                   tcb->entry = (void*)capt_seq_task;
66        if(tcb->entry == (void*)task_InitFileModules)   tcb->entry = (void*)init_file_modules_task;
67        if(tcb->entry == (void*)task_MovieRecord)               tcb->entry = (void*)movie_record_task;
68        if(tcb->entry == (void*)task_ExpDrv)                    tcb->entry = (void*)exp_drv_task;
69}
70
71/*---------------------------------------------------------------------
72  Memory Map:
73        0001900     MEMBASEADDR             start of data - used for initialized vars
74        0010797???                          end of inited data
75        0010798???                          start of bss - used for zeroed/uninited vars
76        016E81F???                          end of bss
77        016E820???  MEMISOSTART             start of our data / bss
78
79        0400000                             raw buffers
80        8000000                             end of raw buffers
81
82        C0xxxxxx                            I/O
83
84        FF810000    ROMBASEADDR             start of rom
85        FFFFFFFF                            end of rom
86----------------------------------------------------------------------*/
87
88/*----------------------------------------------------------------------
89        boot()
90
91        Main entry point for the CHDK code
92-----------------------------------------------------------------------*/
93void __attribute__((naked,noinline)) boot() {
94       
95    asm volatile (
96                "LDR     R1, =0xC0410000\n"
97                "MOV     R0, #0\n"
98                "STR     R0, [R1]\n"
99                "MOV     R1, #0x78\n"
100                "MCR     p15, 0, R1,c1,c0\n"
101                "MOV     R1, #0\n"
102                "MCR     p15, 0, R1,c7,c10, 4\n"
103                "MCR     p15, 0, R1,c7,c5\n"
104                "MCR     p15, 0, R1,c7,c6\n"
105                "MOV     R0, #0x3D\n"
106                "MCR     p15, 0, R0,c6,c0\n"
107                "MOV     R0, #0xC000002F\n"
108                "MCR     p15, 0, R0,c6,c1\n"
109                "MOV     R0, #0x35\n"                                   // memory region & size. bits 1 - 5 = size index, actual size = 2^(size index + 1) = 128MB
110                "MCR     p15, 0, R0,c6,c2\n"
111                "MOV     R0, #0x40000035\n"                             // memory region & size. bits 1 - 5 = size index, actual size = 2^(size index + 1) = 128MB
112                "MCR     p15, 0, R0,c6,c3\n"
113                "MOV     R0, #0x80000017\n"
114                "MCR     p15, 0, R0,c6,c4\n"
115                "LDR     R0, =0xFF80002D\n"
116                "MCR     p15, 0, R0,c6,c5\n"
117                "MOV     R0, #0x34\n"
118                "MCR     p15, 0, R0,c2,c0\n"
119                "MOV     R0, #0x34\n"
120                "MCR     p15, 0, R0,c2,c0, 1\n"
121                "MOV     R0, #0x34\n"
122                "MCR     p15, 0, R0,c3,c0\n"
123                                "LDR     R0, =0x3333330\n"
124                "MCR     p15, 0, R0,c5,c0, 2\n"
125                "LDR     R0, =0x3333330\n"
126                "MCR     p15, 0, R0,c5,c0, 3\n"
127                "MRC     p15, 0, R0,c1,c0\n"
128                "ORR     R0, R0, #0x1000\n"
129                "ORR     R0, R0, #4\n"
130                "ORR     R0, R0, #1\n"
131                "MCR     p15, 0, R0,c1,c0\n"
132                "MOV     R1, #0x80000006\n"
133                "MCR     p15, 0, R1,c9,c1\n"
134                "MOV     R1, #6\n"
135                "MCR     p15, 0, R1,c9,c1, 1\n"
136                "MRC     p15, 0, R1,c1,c0\n"
137                "ORR     R1, R1, #0x50000\n"
138                "MCR     p15, 0, R1,c1,c0\n"
139                "LDR     R2, =0xC0200000\n"
140                "MOV     R1, #1\n"
141                "STR     R1, [R2,#0x10C]\n"
142                "MOV     R1, #0xFF\n"
143                "STR     R1, [R2,#0xC]\n"
144                "STR     R1, [R2,#0x1C]\n"
145                "STR     R1, [R2,#0x2C]\n"
146                "STR     R1, [R2,#0x3C]\n"
147                "STR     R1, [R2,#0x4C]\n"
148                "STR     R1, [R2,#0x5C]\n"
149                "STR     R1, [R2,#0x6C]\n"
150                "STR     R1, [R2,#0x7C]\n"
151                "STR     R1, [R2,#0x8C]\n"
152                "STR     R1, [R2,#0x9C]\n"
153                "STR     R1, [R2,#0xAC]\n"
154                "STR     R1, [R2,#0xBC]\n"
155                "STR     R1, [R2,#0xCC]\n"
156                "STR     R1, [R2,#0xDC]\n"
157                "STR     R1, [R2,#0xEC]\n"
158                "STR     R1, [R2,#0xFC]\n"
159                "LDR     R1, =0xC0400008\n"
160                "LDR     R2, =0x430005\n"
161                "STR     R2, [R1]\n"
162                "MOV     R1, #1\n"
163                "LDR     R2, =0xC0243100\n"
164                "STR     R2, [R1]\n"
165                "LDR     R2, =0xC0242010\n"
166                "LDR     R1, [R2]\n"
167                "ORR     R1, R1, #1\n"
168                "STR     R1, [R2]\n"
169
170                "LDR     R0, =0xFFC8AB88\n"                             // adapted for 101g Firmware
171                "LDR     R1, =0x1900\n"
172                "LDR     R3, =0x1049C\n"
173        "loc_FF00013C:\n"
174                "CMP     R1, R3\n"
175                "LDRCC   R2, [R0],#4\n"
176                "STRCC   R2, [R1],#4\n"
177                "BCC     loc_FF00013C\n"
178                "LDR     R1, =0x1774EC\n"
179                "MOV     R2, #0\n"
180        "loc_FF000154:\n"
181                "CMP     R3, R1\n"
182                "STRCC   R2, [R3],#4\n"
183                "BCC     loc_FF000154\n"
184                               
185                "B       sub_FF000358_my" // -->
186    );
187}
188
189/*----------------------------------------------------------------------
190        sub_FF000358_my
191-----------------------------------------------------------------------*/
192void __attribute__((naked,noinline)) sub_FF000358_my() {
193// FF810358
194
195        //http://chdk.setepontos.com/index.php/topic,4194.0.html
196        *(int*)0x1938=(int)taskHook;
197        *(int*)0x193C=(int)taskHook;
198   
199        // replacement of sub_FF024B5C for correct power-on.
200        // http://chdk.setepontos.com/index.php?topic=6341.msg76409#msg76409
201        *(int*)(0x25F4) = (*(int*)0xC0220130)&1 ? 0x200000 : 0x100000;
202       
203        asm volatile (
204                "LDR     R0, =0xFF8103D0\n"
205                "MOV     R1, #0\n"
206                "LDR     R3, =0xFF810408\n"
207        "loc_FF000364:\n"
208                "CMP     R0, R3\n"
209                "LDRCC   R2, [R0],#4\n"
210                "STRCC   R2, [R1],#4\n"
211                "BCC     loc_FF000364\n"
212                "LDR     R0, =0xFF810408\n"
213                "MOV     R1, #0x4B0\n"
214                "LDR     R3, =0xFF81061C\n"
215        "loc_FF000380:\n"
216                "CMP     R0, R3\n"
217                "LDRCC   R2, [R0],#4\n"
218                "STRCC   R2, [R1],#4\n"
219                "BCC     loc_FF000380\n"
220                "MOV     R0, #0xD2\n"
221                "MSR     CPSR_cxsf, R0\n"
222                "MOV     SP, #0x1000\n"
223                "MOV     R0, #0xD3\n"
224                "MSR     CPSR_cxsf, R0\n"
225                "MOV     SP, #0x1000\n"
226                "LDR     R0, =0x6C4\n"
227                "LDR     R2, =0xEEEEEEEE\n"
228                "MOV     R3, #0x1000\n"
229        "loc_FF0003B4:\n"
230                "CMP     R0, R3\n"
231                "STRCC   R2, [R0],#4\n"
232                "BCC     loc_FF0003B4\n"
233                //"BL      sub_FF0011B0\n"                              // original
234                "BL      sub_FF0011B0_my\n"                     // --> patched
235     );
236}
237
238/*----------------------------------------------------------------------
239        sub_FF0011B0_my
240-----------------------------------------------------------------------*/
241void __attribute__((naked,noinline)) sub_FF0011B0_my() {
242// FF8111B0
243
244     asm volatile (
245                "STR     LR, [SP,#-4]!\n"
246                "SUB     SP, SP, #0x74\n"
247                "MOV     R1, #0x74\n"
248                "MOV     R0, SP\n"
249                "BL      sub_FFB9C68C\n"                                // adapted for 101g Firmware
250                "MOV     R0, #0x53000\n"
251                "STR     R0, [SP,#4]\n"
252#if defined(OPT_CHDK_IN_EXMEM)
253                "LDR     R0, =0x1774EC\n"                               // use original heap offset since CHDK is loaded in high memory
254#else
255                "LDR     R0, =new_sa\n"                                 // otherwise use patched value
256                "LDR     R0, [R0]\n"       
257#endif
258                                "LDR     R2, =0x371F80 \n"
259                                "STR     R0, [SP,#0x8] \n"
260                                "SUB     R0, R2, R0 \n"
261                                "STR     R0, [SP,#0xC] \n"
262                                "MOV     R0, #0x22 \n"
263                                "STR     R0, [SP,#0x18] \n"
264                                "MOV     R0, #0x68 \n"
265                                "STR     R0, [SP,#0x1C] \n"
266                                "LDR     R1, =0x379C00 \n"
267                                "LDR     R0, =0x19B \n"
268                                "STR     R1, [SP] \n"
269                                "STR     R0, [SP,#0x20] \n"
270                                "MOV     R0, #0x96 \n"
271                                "STR     R2, [SP,#0x10] \n"
272                                "STR     R1, [SP,#0x14] \n"
273                                "STR     R0, [SP,#0x24] \n"
274                                "STR     R0, [SP,#0x28] \n"
275                                "MOV     R0, #0x64 \n"
276                                "STR     R0, [SP,#0x2C] \n"
277                                "MOV     R0, #0 \n"
278                                "STR     R0, [SP,#0x30] \n"
279                                "STR     R0, [SP,#0x34] \n"
280                                "MOV     R0, #0x10 \n"
281                                "STR     R0, [SP,#0x5C] \n"
282                                "MOV     R0, #0x800 \n"
283                                "STR     R0, [SP,#0x60] \n"
284                                "MOV     R0, #0xA0 \n"
285                                "STR     R0, [SP,#0x64] \n"
286                                "MOV     R0, #0x280 \n"
287                                "STR     R0, [SP,#0x68] \n"
288                                //"LDR     R1, =sub_FF815EE0 \n"                // original
289                                "LDR     R1, =sub_FF005EE0_my \n"               // --> patched
290                                "B              sub_FF81124C \n"                                // --> continue in firmware
291     );
292}
293
294/*----------------------------------------------------------------------
295        sub_FF005EE0_my
296-----------------------------------------------------------------------*/
297void __attribute__((naked,noinline)) sub_FF005EE0_my() {
298// FF815EE0
299
300        asm volatile (
301                                "STMFD  SP!, {R4,LR} \n"
302                                "BL     sub_FF810B28 \n"
303                                "BL     sub_FF81A374 \n"                                        // dmSetup
304                                "CMP    R0, #0 \n"
305                                //"ADRLT        R0, aDmsetup \n"                        // "dmSetup"
306                                "LDRLT  r0, =0xFF815FF4 \n"
307                                "BLLT   _err_init_task \n"
308                                "BL     sub_FF815B18 \n"
309                                "CMP    R0, #0 \n"
310                                //"ADRLT        R0, aTermdriverinit \n"         // "termDriverInit"
311                                "LDRLT  R0, =0xFF815FFC \n"
312                                "BLLT   _err_init_task \n"
313                                //"ADR  R0, a_term \n"                                  // "/_term"
314                                "LDR    R0, =0xFF81600C \n"
315                                "BL     sub_FF815C00 \n"
316                                "CMP    R0, #0 \n"
317                                //"ADRLT        R0, aTermdevicecrea \n"         // "termDeviceCreate"
318                                "LDRLT  R0, =0xFF816014 \n"
319                                "BLLT   _err_init_task \n"
320                                //"ADR  R0, a_term \n"                                  // "/_term"
321                                "LDR    R0, =0xFF81600C \n"
322                                "BL     sub_FF813CA8 \n"
323                                "CMP    R0, #0 \n"
324                                //"ADRLT        R0, aStdiosetup \n"                     // "stdioSetup"
325                                "LDRLT  R0, =0xFF816028 \n"
326                                "BLLT   _err_init_task \n"
327                                "BL     sub_FF819D00 \n"
328                                "CMP    R0, #0 \n"
329                                //"ADRLT        R0, aStdlibsetup \n"            // "stdlibSetup"
330                                "LDRLT  R0, =0xFF816034 \n"
331                                "BLLT   _err_init_task \n"
332                                "BL     sub_FF811690 \n"
333                                "CMP    R0, #0 \n"
334                                //"ADRLT        R0, aArmlib_setup \n"           // "armlib_setup"
335                                "LDRLT  R0, =0xFF816040 \n"
336                                "BLLT   _err_init_task \n"
337                                "LDMFD  SP!, {R4,LR} \n"
338                                //"B    sub_FF81FCB4 \n"                                // original taskcreate_Startup
339                                "B      taskcreate_Startup_my \n"                       // --> patched
340        );
341};
342
343/*----------------------------------------------------------------------
344        taskcreate_Startup_my
345-----------------------------------------------------------------------*/
346void __attribute__((naked,noinline)) taskcreate_Startup_my() {
347// FF81FCB4
348
349        asm volatile (
350                                "STMFD   SP!, {R3-R9,LR} \n"
351                                "MOV     R6, #0 \n"
352                                //"BL      sub_FF834B44 \n"                     // j_nullsub_107
353                                "BL      sub_FF83D9B0 \n"
354                                "LDR     R9, =0xC0220000 \n"
355                                "MOVS    R7, R0 \n"
356                                "MOV     R8, #1 \n"
357                                "BNE     loc_FF00FCE8 \n"
358                                "BL      sub_FF8372F0 \n"
359                                "CMP     R0, #0 \n"
360                                "BEQ     loc_FF00FCE8 \n"
361                                "LDR     R0, [R9,#0x12C] \n"
362                                "BIC     R5, R8, R0 \n"
363                                "LDR     R0, [R9,#0x128] \n"
364                                "BIC     R4, R8, R0 \n"
365                                "BL      sub_FF833DDC \n"
366                                "CMP     R0, #1 \n"
367                                "MOVEQ   R6, #1 \n"
368                                "ORR     R0, R4, R5 \n"
369                                "ORRS    R0, R0, R6 \n"
370                                "BNE     loc_FF00FCF8 \n"
371                                "BL      sub_FF834190 \n"
372                                "MOV     R0, #0x44 \n"
373                                "STR     R0, [R9,#0x1C] \n"
374                                "BL      sub_FF834380 \n"
375        "loc_FF00FCE4: \n"
376                                "B       loc_FF00FCE4 \n"
377        "loc_FF00FCE8: \n"
378                                "LDR     R0, [R9,#0x128] \n"
379                                "BIC     R4, R8, R0 \n"
380                                "LDR     R0, [R9,#0x12C] \n"
381                                "BIC     R5, R8, R0 \n"
382        "loc_FF00FCF8: \n"
383                                "MOV     R3, R6 \n"
384                                "MOV     R2, R7 \n"
385                                "MOV     R1, R5 \n"
386                                "MOV     R0, R4 \n"
387                                //"BL      sub_FF834B4C \n"
388                                //"BL      sub_FF834B48 \n"                     //j_nullsub_108
389                                "BL      sub_FF83BB7C \n"
390                                "LDR     R1, =0x3CE000 \n"
391                                "MOV     R0, #0 \n"
392                                "BL      sub_FF83BFEC \n"
393                                "BL      sub_FF83BD94 \n"
394                                "MOV     R3, #0 \n"
395                                "STR     R3, [SP] \n"
396                                //"LDR     R3, =task_Startup \n"                // original task_Startup at 0xFF81FBF4
397                                "LDR     R3, =task_Startup_my \n"       // --> patched
398                                "B       sub_FF81FD64 \n"                               // --> continue in firmware
399     );
400}
401
402/*----------------------------------------------------------------------
403        task_Startup_my
404-----------------------------------------------------------------------*/
405void __attribute__((naked,noinline)) task_Startup_my() {
406// 0xFF81FBF4
407       
408        asm volatile (
409                                "STMFD   SP!, {R4,LR} \n"
410                                "BL      sub_FF816588 \n"
411                                "BL      sub_FF835D30 \n"
412                                "BL      sub_FF833DEC \n"
413                                //"BL      sub_FF83D9F8 \n"                     // j_nullsub_110
414                                "BL      sub_FF83DBE4 \n"
415                                "BL      sub_FF834F90 \n"
416                                "BL      sub_FF833870 \n"
417                                //"BL      sub_FF83DA8C \n"                     // start diskboot.bin
418                                "BL      sub_FF83DD90 \n"
419                                "BL      sub_FF816488\n"
420                                "BL      sub_FF836A50\n"                                // taskcreate_PwrCnt()
421                                "LDR     R1, =0x7C007C00\n"
422                                "LDR     R0, =0xC0F1800C\n"
423                "BL      sub_FF835D3C\n"
424                                "LDR     R0, =0xC0F18010\n"
425                                "MOV     R1, #0\n"
426                "BL      sub_FF835D3C\n"
427                                "LDR     R0, =0xC0F18018\n"
428                                "MOV     R1, #0\n"
429                "BL      sub_FF835D3C\n"                                 
430                                "LDR     R0, =0xC0F1801C\n"
431                                "MOV     R1, #1000\n"
432                "BL      sub_FF835D3C\n"
433                                "LDR     R0, =0xC0F18020\n"
434                                "MOV     R1, #8\n"
435                "BL      sub_FF835D3C\n"
436                                "LDR     R0, =0xC022D06C\n"
437                                "MOV     R1, #0xE000000\n"
438                "BL      sub_FF835D3C\n"
439                "BL      sub_FF8164C0\n"
440                                "BL      sub_FF832280\n"
441                "BL      sub_FF83DC14\n"                                // taskcreate_WDT()
442                "BL      sub_FF83B320\n"
443                "BL      sub_FF83DD94\n"                                // taskcreate_CtrlSrv()
444                                "BL      CreateTask_spytask\n"                  // added to create the Spytask (afaik the main CHDK Task)
445                                 //"BL      sub_FF8349EC\n"                             // original taskcreate_PhySw()
446                                 "BL      taskcreatePhySw_my\n"                 // --> patched taskcreate_PhySw()
447                                "BL     sub_FF83927C \n"                     
448                                "BL     sub_FF83DDAC \n"                     
449                                //"BL   sub_FF831678 \n"                                // j_nullsub_101
450                                "BL     sub_FF8331E0 \n"                     
451                                "BL     sub_FF83D76C \n"                     
452                                "BL     sub_FF833824 \n"                     
453                                "BL     sub_FF83317C \n"                     
454                                "BL     sub_FF8322B4 \n"                     
455                                "BL     sub_FF83E9AC \n"                     
456                                "BL     sub_FF833140 \n"                               
457                                "LDMFD  SP!, {R4,LR} \n"                   
458                                "B      sub_FF8166A8 \n"                                        // --> continue in firmware 
459     );
460}
461
462/*----------------------------------------------------------------------
463        taskcreatePhySw_my
464-----------------------------------------------------------------------*/
465void __attribute__((naked,noinline)) taskcreatePhySw_my() {
466// FF8349EC
467       
468        asm volatile (
469                                "STMFD   SP!, {R3-R5,LR}\n"
470                                "LDR     R4, =0x1C3C\n"
471                                "LDR     R0, [R4,#4]\n"
472                                "CMP     R0, #0\n"
473                                "BNE     sub_FF834A20\n"                        // --> continue in firmware
474                                "MOV     R3, #0\n"
475                                "STR     R3, [SP]\n"
476                                //"LDR     R3, =0xFF8349B8 \n"                  // original task_PhySw()
477                                //"MOV     R2, #0x800\n"
478                                "LDR     R3, =mykbd_task\n"                     // --> patched PhySw() mykbd_task (responsible for listening to key presses)
479                                "MOV     R2, #0x2000\n"                                 // stack size for new task_PhySw so we don't have to do stack switch
480                                "B           sub_FF834A10 \n"                           // --> continue in firmware
481        );
482}
483
484/*----------------------------------------------------------------------
485        spytask
486-----------------------------------------------------------------------*/
487void spytask(long ua, long ub, long uc, long ud, long ue, long uf)
488{
489    core_spytask();
490}
491
492/*----------------------------------------------------------------------
493        CreateTask_spytask
494-----------------------------------------------------------------------*/
495void CreateTask_spytask() {
496        _CreateTask("SpyTask", 0x19, 0x2000, spytask, 0);
497}
498
499/*----------------------------------------------------------------------
500        init_file_modules_task
501-----------------------------------------------------------------------*/
502 void __attribute__((naked,noinline)) init_file_modules_task() {
503//FF89E66C
504
505        asm volatile(
506                "STMFD   SP!, {R4-R6,LR}\n"
507                "BL      sub_FF89669C\n"
508                "LDR     R5, =0x5006\n"
509                "MOVS    R4, R0\n"
510                "MOVNE   R1, #0\n"
511                "MOVNE   R0, R5\n"
512                "BLNE    sub_FF89A58C\n"                                // PostLogicalEventToUI
513                "BL      sub_FF8966C8\n"
514                "BL      core_spytask_can_start\n"      // added CHDK: Set "it's-safe-to-start"-Flag for spytask                                 
515                                 "B               sub_FF89E68C\n"                               // --> continue in firmware
516         );
517}                       
518
519///*----------------------------------------------------------------------
520
Note: See TracBrowser for help on using the repository browser.