This source file includes following definitions.
- _run
- _module_can_unload
- _module_exit_alt
- crc32_for_byte
- crc32
- read_file_f
- read_file_o
- compute_file_crc_f
- compute_file_crc_o
- write_file_f
- write_file_o
- read_file
- write_file
- compute_file_crc
- strcasecmp
- mkdir_if_not_exist
- is_parent
- is_current
- fs_readdir
- process_dir
- wordpad
- is_valid_stptr
- iswhitelisted
- get_next_object
- get_object_name
- get_object_data
- fproc_totalsize
- dproc_count
- dproc_store
- fproc_store
- alloc_storage
- restore
- can_boot_from_fat32
- gui_fileshelter_kbd_process
- basic_module_init
- gui_fileshelter_menu_kbd_process
- gui_fileshelter_draw
1 #include "camera_info.h"
2 #include "gui.h"
3 #include "gui_draw.h"
4 #include "meminfo.h"
5 #include "module_load.h"
6 #include "simple_module.h"
7 #include "clock.h"
8 #include "console.h"
9 #include "conf.h"
10 #include "sd_card.h"
11 #include "cachebit.h"
12 #include "exmem.h"
13 #include "time.h"
14 #include "dirent.h"
15 #include "ctype.h"
16
17 #define FSCRC_CALC 1
18
19 #define MAX_PATH_LEN 100
20
21
22
23 static int running = 0;
24 static char osdbuf[128];
25
26 extern int basic_module_init();
27
28
29
30
31
32 int _run()
33 {
34 basic_module_init();
35
36 return 0;
37 }
38
39 int _module_can_unload()
40 {
41 return (running==0);
42 }
43
44 int _module_exit_alt()
45 {
46
47 return 0;
48 }
49
50
51
52 libsimple_sym _librun =
53 {
54 {
55 0, 0, _module_can_unload, _module_exit_alt, _run
56 }
57 };
58
59 ModuleInfo _module_info =
60 {
61 MODULEINFO_V1_MAGICNUM,
62 sizeof(ModuleInfo),
63 {1,0},
64
65 ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,
66 ANY_PLATFORM_ALLOWED,
67
68 (int32_t)"CHDK backup & restore",
69 MTYPE_TOOL,
70
71 &_librun.base,
72
73 CONF_VERSION,
74 CAM_SCREEN_VERSION,
75 ANY_VERSION,
76 ANY_VERSION,
77
78 0,
79 };
80
81
82
83
84
85
86 unsigned long crc32_for_byte(unsigned long r) {
87 unsigned long j;
88 for (j = 0; j < 8; j++) {
89 r = (r & 1? 0: (unsigned long)0xEDB88320) ^ r >> 1;
90 }
91 return r ^ (unsigned long)0xFF000000;
92 }
93
94 void crc32(const void *data, unsigned long n_bytes, unsigned long* crc) {
95 static unsigned long ct[0x100] = {0};
96 unsigned long i;
97 if (!ct[0]) {
98 for (i = 0; i < 0x100; i++) {
99 ct[i] = crc32_for_byte(i);
100 }
101 }
102 for (i = 0; i < n_bytes; i++) {
103 *crc = ct[(unsigned char)*crc ^ ((unsigned char*)data)[i]] ^ *crc >> 8;
104 }
105 }
106
107
108
109
110
111 static int use_open_rather_than_fopen = 1;
112
113 int read_file_f(char *fn, void *buf, int size)
114 {
115 int ret = -1;
116 FILE *fd = fopen(fn, "r+b");
117 if (fd) {
118 ret = fread(buf, 1, size, fd);
119 fclose(fd);
120 if (ret == size) {
121 ret = 0;
122 }
123 else {
124 ret = 1;
125 }
126 }
127 return ret;
128 }
129
130 int read_file_o(char *fn, void *buf, int size)
131 {
132 int ret = -1;
133 int fd = open(fn, O_RDONLY, 0777);
134 if (fd >= 0) {
135 ret = read(fd, buf, size);
136 close(fd);
137 if (ret == size) {
138 ret = 0;
139 }
140 else {
141 ret = 1;
142 }
143 }
144 return ret;
145 }
146
147 int compute_file_crc_f(char *fn, void *buf, int size, int bufsize, unsigned long *crc)
148 {
149 int ret = 0;
150 if (!fn || !buf || !crc || !bufsize) {
151 return -1;
152 }
153 FILE *fd = fopen(fn, "r+b");
154 if (fd) {
155 long chunk = bufsize<size?bufsize:size;
156 while (1) {
157 long r = fread(buf, 1, chunk, fd);
158 if (r != chunk) {
159 if (r != size) {
160 ret = 1;
161 break;
162 }
163 }
164 crc32(buf, r, crc);
165 size -= r;
166 if (size <= 0) {
167 break;
168 }
169 }
170 fclose(fd);
171 }
172 return ret;
173 }
174
175 int compute_file_crc_o(char *fn, void *buf, int size, int bufsize, unsigned long *crc)
176 {
177 int ret = 0;
178 if (!fn || !buf || !crc || !bufsize) {
179 return -1;
180 }
181 int fd = open(fn, O_RDONLY, 0777);
182 if (fd >= 0) {
183 long chunk = bufsize<size?bufsize:size;
184 while (1) {
185 long r = read(fd, buf, chunk);
186 if (r != chunk) {
187 if (r != size) {
188 ret = 1;
189 break;
190 }
191 }
192 crc32(buf, r, crc);
193 size -= r;
194 if (size <= 0) {
195 break;
196 }
197 }
198 close(fd);
199 }
200 return ret;
201 }
202
203 int write_file_f(char *fn, void *buf, int size)
204 {
205 int ret = -1;
206 FILE *fd = fopen(fn, "w+b");
207 if (fd) {
208 ret = fwrite(buf, 1, size, fd);
209 fclose(fd);
210 if (ret == size) {
211 ret = 0;
212 }
213 else {
214 ret = 1;
215 }
216 }
217 return ret;
218 }
219
220 int write_file_o(char *fn, void *buf, int size)
221 {
222 int ret = -1;
223 int fd = open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0777);
224 if (fd >= 0) {
225 ret = write(fd, buf, size);
226 close(fd);
227 if (ret == size) {
228 ret = 0;
229 }
230 else {
231 ret = 1;
232 }
233 }
234 return ret;
235 }
236
237
238
239 int read_file(char *fn, void *buf, int size)
240 {
241 if (use_open_rather_than_fopen) {
242 return read_file_o(fn, buf, size);
243 }
244 return read_file_f(fn, buf, size);
245 }
246
247
248
249 int write_file(char *fn, void *buf, int size)
250 {
251 if (use_open_rather_than_fopen) {
252 return write_file_o(fn, buf, size);
253 }
254 return write_file_f(fn, buf, size);
255 }
256
257
258
259 int compute_file_crc(char *fn, void *buf, int size, int bufsize, unsigned long *crc)
260 {
261 if (use_open_rather_than_fopen) {
262 return compute_file_crc_o(fn, buf, size, bufsize, crc);
263 }
264 return compute_file_crc_f(fn, buf, size, bufsize, crc);
265 }
266
267
268
269
270
271 int strcasecmp(const char *s1, const char *s2)
272 {
273 const unsigned char *p1 = (const unsigned char *) s1;
274 const unsigned char *p2 = (const unsigned char *) s2;
275 int result;
276 if (p1 == p2)
277 return 0;
278 while ((result = tolower(*p1) - tolower(*p2++)) == 0)
279 if (*p1++ == '\0')
280 break;
281 return result;
282 }
283
284
285
286
287
288 long mkdir_if_not_exist(const char *dirname)
289 {
290
291 if (stat(dirname,0) != 0) return mkdir(dirname);
292 return 0;
293 }
294
295
296
297
298
299 typedef struct
300 {
301 struct dirent *de;
302 unsigned long size;
303 unsigned long mtime;
304 unsigned char deleted;
305 unsigned char isdir;
306 unsigned char isparent;
307 unsigned char iscurrent;
308 unsigned char isvalid;
309 unsigned char ishidden;
310 } fs_dirent;
311
312 static int is_parent(const char *name) { return (strcmp(name, "..") == 0); }
313 static int is_current(const char *name) { return (strcmp(name, ".") == 0); }
314
315
316
317
318 static int fs_readdir(DIR *d, fs_dirent *de, const char* path)
319 {
320 char pbuf[MAX_PATH_LEN];
321
322 de->de = readdir(d);
323 de->size = 0;
324 de->mtime = 0;
325 de->deleted = 0;
326 de->isparent = 0;
327 de->iscurrent = 0;
328 de->isdir = 0;
329 de->isvalid = 0;
330 de->ishidden = 0;
331
332 if (de->de)
333 {
334 if (de->de->d_name[0] == 0xE5)
335 {
336 de->deleted = 1;
337 }
338 else
339 {
340 de->isparent = is_parent(de->de->d_name);
341 de->iscurrent = is_current(de->de->d_name);
342
343 sprintf(pbuf, "%s%s%s", path, path[strlen(path)-1]=='/'?"":"/", de->de->d_name);
344 struct stat st;
345 if (de->isparent || de->iscurrent)
346 {
347 de->isdir = 1;
348 de->isvalid = 1;
349 }
350 else if (stat(pbuf, &st) == 0)
351 {
352 de->size = st.st_size;
353 de->mtime = st.st_mtime;
354 de->isvalid = 1;
355 de->isdir = ((st.st_attrib & DOS_ATTR_DIRECTORY) != 0);
356 de->ishidden = ((st.st_attrib & DOS_ATTR_HIDDEN) != 0);
357 }
358 }
359
360 return 1;
361 }
362
363 return 0;
364 }
365
366
367
368
369
370 static void process_dir(const char *parent, const char *name, int nested, void (*file_process)(const char *path, const char *file, fs_dirent *de), void (*dir_process)(const char *path, fs_dirent *de))
371 {
372 DIR *d;
373 fs_dirent de;
374
375
376 char *path;
377 if (name)
378 {
379 path = malloc(strlen(parent) + strlen(name) + 2);
380 sprintf(path, "%s%s%s", parent, parent[strlen(parent)-1]=='/'?"":"/", name);
381 }
382 else
383 {
384 path = (char*)parent;
385 }
386
387
388 d = opendir_chdk(path,OPENDIR_FL_CHDK_LFN);
389
390 if (d)
391 {
392
393 if (dir_process)
394 dir_process(path, &de);
395
396
397 while (fs_readdir(d, &de, path))
398 {
399 if (!de.deleted)
400 {
401
402 if (de.isdir)
403 {
404 if (!de.isparent && !de.iscurrent && nested)
405 process_dir(path, de.de->d_name, nested-1, file_process, dir_process);
406 }
407 else if (file_process)
408 {
409 file_process(path, de.de->d_name, &de);
410 }
411 }
412 }
413 closedir(d);
414
415 }
416
417 if (name)
418 free(path);
419 }
420
421
422
423
424
425
426
427
428
429
430
431
432
433 #define FMAGIC 0x004c4946
434 #define DMAGIC 0x00524944
435
436 enum rstatus {
437 RS_OK = 0,
438 RS_NAMELONG,
439 RS_CRC,
440 RS_FERR,
441 };
442
443
444 const char *rsshumanL[] = {
445 "OK",
446 "Files not backed up",
447 "Stored files corrupted",
448 "Stored files corrupted",
449 "Storage area corrupted",
450 "A/CHDK exists, aborting",
451 };
452
453
454 typedef struct
455 {
456 unsigned long magic;
457 unsigned long size;
458 unsigned long mtime;
459 unsigned long nlen;
460 unsigned long crc;
461 unsigned long status;
462 } fs_fheader;
463
464
465
466 const char *wl1[] = {"DISKBOOT.BIN", "PS.FIR", "PS.FI2", 0};
467 static void *whitelist = 0;
468 static unsigned storageneed = 0;
469 static unsigned filecount = 0;
470 static unsigned failcount = 0;
471 static unsigned dircount = 0;
472 static unsigned tfilecount = 0;
473 static unsigned tdircount = 0;
474 static unsigned fileprocd = 0;
475 static unsigned dirprocd = 0;
476 static void *starea = 0;
477 static unsigned stmax = 0;
478 static void *tmpbuf = 0;
479 const unsigned tmpsiz = 32768;
480 static void *storptr = 0;
481 static unsigned long stcrc = 0;
482
483 unsigned wordpad(unsigned u)
484 {
485 return (u + 3) & 0xfffffffc;
486 }
487
488
489 int is_valid_stptr(void *p)
490 {
491 if (p>starea+stmax-sizeof(fs_fheader) || p<starea) {
492 return 0;
493 }
494 return 1;
495 }
496
497
498
499
500 int iswhitelisted(const char *name)
501 {
502 if (whitelist == 0) {
503 return 1;
504 }
505 char **wl = whitelist;
506 char *s = *wl;
507 while (s) {
508 if (strcasecmp(name, s) == 0) {
509 return 1;
510 }
511 s = *(++wl);
512 }
513 return 0;
514 }
515
516
517
518
519 int get_next_object(unsigned long magic, void **currptr)
520 {
521 char *p = *currptr;
522 if (!is_valid_stptr(p)) {
523 return 0;
524 }
525 fs_fheader *fh = (void*)p;
526 while (fh->magic==FMAGIC || fh->magic==DMAGIC) {
527 p += sizeof(fs_fheader) + wordpad(fh->nlen) + wordpad(fh->size);
528 if (!is_valid_stptr(p)) {
529 break;
530 }
531 fh = (void*)p;
532 if (!magic || fh->magic == magic) {
533 *currptr = (void*)p;
534 return 1;
535 }
536 }
537 return 0;
538 }
539
540
541 char *get_object_name(void *p)
542 {
543 if (!is_valid_stptr(p)) {
544 return 0;
545 }
546 fs_fheader *fh = p;
547 p += sizeof(fs_fheader);
548 if (!is_valid_stptr(p) || !is_valid_stptr(p+fh->nlen)) {
549 return 0;
550 }
551 return (char*)p;
552 }
553
554
555 char *get_object_data(void *p)
556 {
557 if (!is_valid_stptr(p)) {
558 return 0;
559 }
560 fs_fheader *fh = p;
561 p += sizeof(fs_fheader) + wordpad(fh->nlen);
562 if (!is_valid_stptr(p) || !is_valid_stptr(p+fh->size)) {
563 return 0;
564 }
565 return (char*)p;
566 }
567
568
569 void fproc_totalsize(const char *path, const char *file, fs_dirent *de)
570 {
571 if (whitelist && !iswhitelisted(file)) return;
572 storageneed += wordpad(de->size);
573 storageneed += wordpad(strlen(path) + 1 + strlen(file) + 1);
574 storageneed += sizeof(fs_fheader);
575 filecount += 1;
576 }
577
578
579 void dproc_count(const char *path, __attribute__ ((unused))fs_dirent *de)
580 {
581 if (whitelist && !iswhitelisted(path)) return;
582 storageneed += wordpad(strlen(path) + 1);
583 storageneed += sizeof(fs_fheader);
584 dircount += 1;
585 }
586
587
588 void dproc_store(const char *path, fs_dirent *de)
589 {
590 if (whitelist && !iswhitelisted(path)) return;
591 fs_fheader *fh = storptr;
592 fh->magic = DMAGIC;
593 fh->size = 0;
594 fh->mtime = de->mtime;
595 fh->nlen = strlen(path) + 1;
596 fh->crc = 0;
597 storptr += sizeof(fs_fheader);
598 strcpy(storptr, path);
599 storptr += wordpad(fh->nlen);
600 dirprocd++;
601 }
602
603
604 void fproc_store(const char *path, const char *file, fs_dirent *de)
605 {
606 if (whitelist && !iswhitelisted(file)) return;
607 fs_fheader *fh = storptr;
608 fh->magic = FMAGIC;
609 fh->size = de->size;
610 fh->mtime = de->mtime;
611 fh->nlen = strlen(path) + 1 + strlen(file) + 1;
612 fh->crc = 0;
613 storptr += sizeof(fs_fheader);
614 sprintf(storptr, "%s%s%s", path, path[strlen(path)-1]=='/'?"":"/", file);
615 char *name = storptr;
616 storptr += wordpad(fh->nlen);
617
618 if ( read_file(name, storptr, fh->size) ) {
619 failcount++;
620 storptr -= sizeof(fs_fheader);
621 storptr -= wordpad(fh->nlen);
622 console_add_line(file);
623 }
624 else {
625 crc32(storptr, fh->size, &fh->crc);
626 storptr += wordpad(fh->size);
627 fileprocd++;
628 }
629 }
630
631
632
633
634 void alloc_storage()
635 {
636 const char *exmemtypes[] = {"EXMEM_FIRMUP", "EXMEM_FAMODE", 0};
637 const unsigned cushion = 128;
638 unsigned n, i;
639 exmem_alloc_info ai;
640 storageneed += sizeof(fs_fheader);
641 storageneed += tmpsiz;
642 starea = 0;
643 i = 0;
644 while (exmemtypes[i]) {
645 for (n=0; n<exmem_type_count; n++) {
646 if (strncmp(exmemtypes[i],get_exmem_type_name(n),strlen(exmemtypes[i]))==0) {
647 get_exmem_type_status(n, &ai);
648 if (!ai.len) {
649 starea = exmem_alloc_uncached(n, storageneed+cushion, 0);
650 get_exmem_type_status(n, &ai);
651 if (ai.len-cushion < storageneed) {
652 starea = 0;
653 exmem_free_uncached(n);
654 char buf[64];
655 sprintf(buf,"%s need %x got %x",exmemtypes[i],storageneed,ai.len);
656 console_add_line(buf);
657 }
658 #if 1
659 else {
660 char buf[64];
661 sprintf(buf,"%s adr %x",exmemtypes[i],starea);
662 console_add_line(buf);
663 }
664 #endif
665 }
666 break;
667 }
668 }
669 if (starea) {
670 starea += cushion/2;
671 stmax = storageneed - tmpsiz;
672 tmpbuf = starea + stmax;
673 storptr = starea;
674 break;
675 }
676 i++;
677 }
678 }
679
680
681
682
683 int restore(const char *dest, int test)
684 {
685 char buf[256];
686 int ret = 0;
687 if (!starea) {
688 return 1;
689 }
690 if (!test && strlen(dest)>2) mkdir_if_not_exist(dest);
691 storptr = starea;
692 if (!is_valid_stptr(storptr)) {
693 return 2;
694 }
695 fs_fheader *fh = storptr;
696 while (1) {
697 if (fh->magic==DMAGIC) {
698 char *lastdir = get_object_name(storptr);
699 lastdir += 2;
700 if (strlen(dest)+1+strlen(lastdir) > 255) {
701 fh->status = RS_NAMELONG;
702 ret |= 0x40000000;
703 if (!get_next_object(0, &storptr)) {
704 break;
705 }
706 continue;
707 }
708 sprintf(buf,"%s/%s",dest,lastdir);
709 if (!test) {
710 ret |= mkdir_if_not_exist(buf)?0x20000000:0;
711 if (stat(buf,0) == 0) {
712 tdircount--;
713 }
714 }
715 else {
716 msleep(10);
717 tdircount--;
718 }
719 }
720 else if (fh->magic==FMAGIC) {
721 if (strlen(dest)+1+fh->nlen-2 > 255) {
722 fh->status = RS_NAMELONG;
723 ret |= 0x40000000;
724 if (!get_next_object(0, &storptr)) {
725 break;
726 }
727 continue;
728 }
729 unsigned long crc = 0;
730 char *fn = get_object_name(storptr);
731 if (fn) {
732 fn +=2;
733 }
734 else {
735 return ret + 3;
736 }
737 char *fd = get_object_data(storptr);
738 if (fd) {
739 crc32(fd, fh->size, &crc);
740 if (crc != fh->crc) {
741 fh->status = RS_CRC;
742 ret |= 0x10000000;
743 if (!get_next_object(0, &storptr)) {
744 break;
745 }
746 continue;
747 }
748 }
749 sprintf(buf,"%s/%s",dest,fn);
750 if (!test) {
751
752 if ( write_file(buf, fd, fh->size) ) {
753 console_add_line(fn);
754 fh->status = RS_FERR;
755 ret |= 0x08000000;
756 }
757 else {
758 #if (FSCRC_CALC == 1)
759 crc = 0;
760 if ( compute_file_crc(buf, tmpbuf, fh->size, tmpsiz, &crc) ) {
761 console_add_line(fn);
762 fh->status = RS_FERR;
763 ret |= 0x04000000;
764 }
765 else {
766 if ( fh->crc != crc) {
767 console_add_line(fn);
768 fh->status = RS_FERR;
769 ret |= 0x02000000;
770 }
771 else {
772 struct utimbuf t;
773 t.actime = t.modtime = fh->mtime;
774 utime(buf, &t);
775 tfilecount--;
776 }
777 }
778 #else
779 struct utimbuf t;
780 t.actime = t.modtime = fh->mtime;
781 utime(buf, &t);
782 tfilecount--;
783 #endif
784 }
785
786 }
787 else {
788 msleep(10);
789 tfilecount--;
790 }
791 }
792 else {
793 break;
794 }
795
796
797 if (!get_next_object(0, &storptr)) {
798 ret += 4;
799 break;
800 }
801 fh = storptr;
802 }
803 return ret;
804 }
805
806
807
808 int can_boot_from_fat32()
809 {
810 if (conf.platformid > 0x3222) {
811 return 1;
812 }
813 return 0;
814 }
815
816
817
818 char *help1[] = {
819 "Utility for temporarily storing CHDK",
820 "system files in RAM, allowing to format",
821 "card via Canon menu.",
822 "Usage:",
823 "1. Start this utility, press SET to backup",
824 "2. Leave the utility, format card in Canon",
825 " menu. Do NOT switch off the camera.",
826 "3. Start this utility again, press SET",
827 "4. Make card bootable via CHDK menu",
828 "5. Restart camera before starting to shoot",
829 "IMPORTANT",
830 "Do not format card if you get errors.",
831 "Only the following files are stored:",
832 "- Everything in CHDK directory.",
833 "- DISKBOOT.BIN, PS.FIR, PS.FI2",
834 "WARNING",
835
836
837
838
839 "Excessive amount of data in CHDK direcory",
840 "may cause a crash while making backup!",
841 "Do not use this on mission critical files!",
842 };
843
844 char *help_partwarn = "Do NOT format, card will lose partitions!";
845 char *help_bootwarn = "Card will lose autoboot if formatted!";
846
847
848
849
850
851
852 #include "gui_mbox.h"
853 #include "keyboard.h"
854
855 void gui_fileshelter_menu_kbd_process();
856 int gui_fileshelter_kbd_process();
857 void gui_fileshelter_draw();
858
859 gui_handler GUI_MODE_FILESHELTER =
860 { GUI_MODE_MODULE, gui_fileshelter_draw, gui_fileshelter_kbd_process, gui_fileshelter_menu_kbd_process, 0, 0 };
861
862 static unsigned int cardsize;
863 static int canfat32boot;
864 static int partcount;
865 static int noformatyet;
866
867 static int fileshelter_mode = 0;
868 static unsigned disph = 0, dispw = 0, helph = 0;
869 static unsigned restore_status;
870 static unsigned scrolly;
871 static int fileshelter_redraw;
872 gui_handler *fileshelter_old_guimode;
873
874 int gui_fileshelter_kbd_process()
875 {
876 switch (kbd_get_autoclicked_key())
877 {
878 case KEY_SET:
879 if (starea) {
880 if (stat("A/CHDK",0) != 0) {
881
882 unsigned long crc = 0;
883 tfilecount = filecount;
884 tdircount = dircount;
885 fileshelter_redraw = 8;
886 msleep(100);
887 crc32(starea, stmax, &crc);
888 if (crc == stcrc) {
889 fileshelter_redraw = 5;
890 restore_status = restore("A",0);
891 fileshelter_redraw = 3;
892 }
893 else {
894 restore_status = 4;
895 fileshelter_redraw = 3;
896 }
897 }
898 else {
899
900 unsigned long crc = 0;
901 tfilecount = filecount;
902 tdircount = dircount;
903 fileshelter_redraw = 8;
904 msleep(100);
905 crc32(starea, stmax, &crc);
906 if (crc == stcrc) {
907 fileshelter_redraw = 11;
908 restore_status = restore("A",1);
909 fileshelter_redraw = 10;
910 }
911 else {
912 restore_status = 4;
913 fileshelter_redraw = 10;
914 }
915 }
916 }
917 else {
918 fileshelter_redraw = 6;
919 storageneed = 0;
920 filecount = 0;
921 dircount = 0;
922 whitelist = wl1;
923 process_dir("A/", 0, 0, fproc_totalsize, dproc_count);
924 whitelist = 0;
925 process_dir("A/CHDK", 0, 999, fproc_totalsize, dproc_count);
926 alloc_storage();
927 if (starea) {
928 fileshelter_redraw = 7;
929 failcount = 0;
930 fileprocd = 0;
931 dirprocd = 0;
932 whitelist = wl1;
933 process_dir("A/", 0, 0, fproc_store, dproc_store);
934 whitelist = 0;
935 process_dir("A/CHDK", 0, 999, fproc_store, dproc_store);
936 fs_fheader *fh = storptr;
937 fh->magic = 0;
938 stcrc = 0;
939 crc32(starea, stmax, &stcrc);
940 }
941 fileshelter_redraw = 1;
942 }
943 break;
944 case KEY_DOWN:
945 if (scrolly < sizeof(help1)/sizeof(char*)-1) {
946 scrolly++;
947 }
948 else {
949 scrolly = 0;
950 }
951 fileshelter_redraw = 4;
952 break;
953 case KEY_UP:
954 if (scrolly > 0) {
955 scrolly--;
956 }
957 else {
958 scrolly = sizeof(help1)/sizeof(char*)-1;
959 }
960 fileshelter_redraw = 4;
961 break;
962 case KEY_SHOOT_HALF:
963 fileshelter_mode = fileshelter_mode==0?1:0;
964 #if 0
965 if (fileshelter_mode) {
966 use_open_rather_than_fopen = 0;
967 }
968 else {
969 use_open_rather_than_fopen = 1;
970 }
971 #endif
972 fileshelter_redraw = 2;
973 break;
974 }
975 return 0;
976 }
977
978
979
980 int basic_module_init()
981 {
982 if (!running) {
983 running = 1;
984 disph = camera_screen.height / FONT_HEIGHT;
985 dispw = camera_screen.width / FONT_WIDTH;
986 helph = camera_screen.height / FONT_HEIGHT - 5;
987 noformatyet = 1;
988 }
989 else {
990 noformatyet = stat("A/CHDK",0)?0:1;
991 }
992 scrolly = 0;
993
994 cardsize = GetTotalCardSpaceKb();
995 partcount = get_part_count();
996 canfat32boot = can_boot_from_fat32();
997
998 fileshelter_redraw = 2;
999 fileshelter_old_guimode = gui_set_mode(&GUI_MODE_FILESHELTER);
1000 return 1;
1001 }
1002
1003 void gui_fileshelter_menu_kbd_process()
1004 {
1005 if (!starea) {
1006 running = 0;
1007 }
1008
1009 gui_set_mode(fileshelter_old_guimode);
1010 }
1011
1012 void gui_fileshelter_draw()
1013 {
1014 static int selfupdate = 0;
1015 static int warnshown = 0;
1016
1017 int fredraw = fileshelter_redraw;
1018 fileshelter_redraw = 0;
1019
1020 if (fredraw || selfupdate) {
1021
1022 if (fredraw == 2)
1023 {
1024 draw_rectangle(camera_screen.disp_left, 0, camera_screen.disp_right, camera_screen.height-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1025 draw_string(camera_screen.disp_left, 0, "CHDK backup & restore utility", MAKE_COLOR(COLOR_WHITE, COLOR_BLACK));
1026 draw_string(camera_screen.disp_left, FONT_HEIGHT, !starea?"SET-backup MENU-exit \x18\x19-help":noformatyet?"SET-check MENU-exit \x18\x19-help":"SET-restore MENU-exit \x18\x19-help", MAKE_COLOR(COLOR_BLACK, COLOR_WHITE));
1027
1028 #if 0
1029 if (fileshelter_mode) {
1030 draw_char(camera_screen.disp_left+FONT_WIDTH*30, 0, '*', MAKE_COLOR(COLOR_BLACK, COLOR_BLUE));
1031 }
1032 else {
1033 draw_char(camera_screen.disp_left+FONT_WIDTH*30, 0, ' ', MAKE_COLOR(COLOR_BLACK, COLOR_BLUE));
1034 }
1035 #endif
1036
1037 fredraw = 4;
1038 selfupdate = 0;
1039 }
1040 if (fredraw == 3)
1041 {
1042 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1043 if (tfilecount || tdircount) {
1044 sprintf(osdbuf, "Not restored: %u files, %u dirs", tfilecount, tdircount);
1045 if (sizeof(osdbuf)>dispw) osdbuf[dispw] = 0;
1046 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, COLOR_YELLOW));
1047 }
1048 unsigned rssl = restore_status & 0xff;
1049 char *hrsm = "???";
1050 if (rssl < sizeof(rsshumanL)/sizeof(char*)) {
1051 hrsm = (char*)rsshumanL[rssl];
1052 }
1053 sprintf(osdbuf, restore_status?"Restore status: %08x":"Restore status:", restore_status);
1054 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, restore_status?COLOR_RED:COLOR_GREEN));
1055 sprintf(osdbuf, "%s", hrsm);
1056 draw_string(camera_screen.disp_left, 4*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, restore_status?COLOR_RED:COLOR_GREEN));
1057 selfupdate = 0;
1058 }
1059 if (fredraw == 10)
1060 {
1061 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1062 if (tfilecount || tdircount) {
1063 sprintf(osdbuf, "Failed: %u files, %u dirs", tfilecount, tdircount);
1064 if (sizeof(osdbuf)>dispw) osdbuf[dispw] = 0;
1065 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, COLOR_YELLOW));
1066 }
1067 unsigned rssl = restore_status & 0xff;
1068 char *hrsm = "???";
1069 if (rssl < sizeof(rsshumanL)/sizeof(char*)) {
1070 hrsm = (char*)rsshumanL[rssl];
1071 }
1072 sprintf(osdbuf, restore_status?"Test status: %08x":"Test status:", restore_status);
1073 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, restore_status?COLOR_RED:COLOR_GREEN));
1074 sprintf(osdbuf, "%s", hrsm);
1075 draw_string(camera_screen.disp_left, 4*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, restore_status?COLOR_RED:COLOR_GREEN));
1076 selfupdate = 0;
1077 }
1078 if (fredraw == 1)
1079 {
1080 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1081 sprintf(osdbuf, "%u files, %u dirs, total %u bytes", filecount, dircount, storageneed);
1082 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, COLOR_WHITE));
1083 if (starea && !failcount) {
1084 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, "Backup successful", MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1085 }
1086 else if (failcount) {
1087 sprintf(osdbuf, "Backup failed to store %u file(s)", failcount);
1088 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, COLOR_YELLOW));
1089 draw_string(camera_screen.disp_left, 4*FONT_HEIGHT, "See CHDK console for filename(s)", MAKE_COLOR(COLOR_BLACK, COLOR_YELLOW));
1090 }
1091 else if (!starea) {
1092 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, "Backup failed - insufficient memory", MAKE_COLOR(COLOR_BLACK, COLOR_RED));
1093 }
1094 else {
1095 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, "Backup failed", MAKE_COLOR(COLOR_BLACK, COLOR_RED));
1096 }
1097 selfupdate = 0;
1098 }
1099 if (fredraw == 4)
1100 {
1101 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*5, camera_screen.disp_right, camera_screen.height-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1102 unsigned y;
1103 for (y=0; y<helph; y++) {
1104 if (scrolly+y < sizeof(help1)/sizeof(char*)) {
1105 draw_string(camera_screen.disp_left, (5+y)*FONT_HEIGHT, help1[scrolly+y], MAKE_COLOR(COLOR_BLACK, COLOR_GREY));
1106 }
1107 }
1108 if (!warnshown) {
1109 warnshown = 1;
1110 fredraw = 9;
1111 }
1112 selfupdate = 0;
1113 }
1114 if (fredraw == 5)
1115 {
1116 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1117 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, "Restoring ...", MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1118 selfupdate = 5;
1119 }
1120 if (fredraw == 11)
1121 {
1122 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1123 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, "Testing ...", MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1124 selfupdate = 5;
1125 }
1126 if (fredraw == 6)
1127 {
1128 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1129 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, "Counting ...", MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1130 selfupdate = 6;
1131 }
1132 if (fredraw == 7)
1133 {
1134 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1135 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, "Backing up ...", MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1136 selfupdate = 7;
1137 }
1138 if (fredraw == 8)
1139 {
1140 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1141 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, "Verifying integrity ...", MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1142 selfupdate = 6;
1143 }
1144 if (fredraw == 9)
1145 {
1146 draw_rectangle(camera_screen.disp_left, FONT_HEIGHT*2, camera_screen.disp_right, FONT_HEIGHT*5-1, MAKE_COLOR(COLOR_BLACK, COLOR_BLACK), RECT_BORDER0|DRAW_FILLED);
1147
1148
1149 if (canfat32boot && cardsize>32*1024*1024) {
1150 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, help_bootwarn, MAKE_COLOR(COLOR_BLACK, COLOR_RED));
1151 }
1152 else if (!canfat32boot && cardsize>2*1024*1024) {
1153 draw_string(camera_screen.disp_left, 2*FONT_HEIGHT, help_bootwarn, MAKE_COLOR(COLOR_BLACK, COLOR_RED));
1154 }
1155 if (partcount > 1) {
1156 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, help_partwarn, MAKE_COLOR(COLOR_BLACK, COLOR_RED));
1157 }
1158
1159 }
1160
1161 if (selfupdate == 5) {
1162 static unsigned fc=0,dc=0;
1163 if ((tfilecount!=fc) || (tdircount!=dc)) {
1164 sprintf(osdbuf, "Remaining: %u files, %u dirs ", tfilecount, tdircount);
1165 if (sizeof(osdbuf)>dispw) osdbuf[dispw] = 0;
1166 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1167 }
1168 fc = tfilecount;
1169 dc = tdircount;
1170 }
1171 else if (selfupdate == 6) {
1172 static int phase = 0;
1173 const char *pc = "/-\\|";
1174 draw_char(camera_screen.disp_left, 3*FONT_HEIGHT, pc[phase&3], MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1175 phase++;
1176 }
1177 else if (selfupdate == 7) {
1178 static unsigned fc=0,dc=0;
1179 if ((fileprocd!=fc) || (dirprocd!=dc)) {
1180 sprintf(osdbuf, "Remaining: %u files, %u dirs ", filecount-fileprocd, dircount-dirprocd);
1181 if (sizeof(osdbuf)>dispw) osdbuf[dispw] = 0;
1182 draw_string(camera_screen.disp_left, 3*FONT_HEIGHT, osdbuf, MAKE_COLOR(COLOR_BLACK, COLOR_GREEN));
1183 }
1184 fc = fileprocd;
1185 dc = dirprocd;
1186 }
1187
1188 }
1189
1190 }
1191