root/ar5315_microredboot/microredboot/ecos/packages/redboot/current/src/flash.c

Revision 12368, 42.3 kB (checked in by BrainSlayer, 5 months ago)

tftp server added, supports wiligear, ubiquiti and dd-wrt webflash format

Line 
1 //==========================================================================
2 //
3 //      flash.c
4 //
5 //      RedBoot - FLASH memory support
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
12 // Copyright (C) 2003, 2004 Gary Thomas
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 //
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):    gthomas
45 // Contributors: gthomas, tkoeller
46 // Date:         2000-07-28
47 // Purpose:     
48 // Description: 
49 //             
50 // This code is part of RedBoot (tm).
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <redboot.h>
57 #include <cyg/io/flash.h>
58 #include <fis.h>
59 #include <sib.h>
60 #include <cyg/infra/cyg_ass.h>         // assertion macros
61
62 //#define CYGPRI_REDBOOT_7ZIP_FLASH 1;
63
64 #ifdef CYGPRI_REDBOOT_7ZIP_FLASH
65 #include <lzma.h>
66 #endif
67
68 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
69 // Note horrid intertwining of functions, to save precious FLASH
70 extern void conf_endian_fixup(void *p);
71 #endif
72
73 // Round a quantity up
74 #define _rup(n,s) ((((n)+(s-1))/s)*s)
75
76 /*RedBoot_cmd("bdmove",
77         "Move Atheros Board Data information",
78         "",
79         do_bdmove
80     );
81
82 RedBoot_cmd("bdrestore",
83         "Restore Atheros Board Data information",
84         "",
85         do_bdrestore
86     );
87 */
88 #ifdef CYGOPT_REDBOOT_FIS
89 // Image management functions
90 local_cmd_entry("init",
91                 "Initialize FLASH Image System [FIS]",
92                 "[-f]",
93                 fis_init_comp,
94                 FIS_cmds
95     );
96 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
97 # define FIS_LIST_OPTS "[-c] [-d]"
98 #else
99 # define FIS_LIST_OPTS "[-d]"
100 #endif
101 local_cmd_entry("list",
102                 "Display contents of FLASH Image System [FIS]",
103                 FIS_LIST_OPTS,
104                 fis_list,
105                 FIS_cmds
106     );
107 /*local_cmd_entry("free",
108                 "Display free [available] locations within FLASH Image System [FIS]",
109                 "",
110                 fis_free,
111                 FIS_cmds
112     );
113 local_cmd_entry("delete",
114                 "Delete an image from FLASH Image System [FIS]",
115                 "name",
116                 fis_delete,
117                 FIS_cmds
118     );*/
119 int page_programming_supported = 0;
120 int page_gpio = 0;
121
122 static char fis_load_usage[] =
123 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
124                       "[-d] "
125 #endif
126 #ifdef CYGPRI_REDBOOT_7ZIP_FLASH
127                        "[-l] "
128 #endif
129
130                       "[-b <memory_load_address>] [-c] name";
131
132 local_cmd_entry("load",
133                 "Load image from FLASH Image System [FIS] into RAM",
134                 fis_load_usage,
135                 fis_load,
136                 FIS_cmds
137     );
138 local_cmd_entry("create",
139                 "Create an image",
140                 "-b <mem_base> -l <image_length> [-s <data_length>]\n"
141                 "      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
142                 fis_create,
143                 FIS_cmds
144     );
145 #if defined(CYGPKG_HAL_MIPS_AR2316)
146 local_cmd_entry("create256",
147                 "Create an image",
148                 "-b <mem_base> -l <image_length> [-s <data_length>]\n"
149                 "      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
150                 fis_create_256,
151                 FIS_cmds
152     );
153 local_cmd_entry("createaccton",
154                 "Create an image",
155                 "-b <mem_base> -l <image_length> [-s <data_length>]\n"
156                 "      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
157                 fis_create_accton,
158                 FIS_cmds
159     );
160 #endif
161 #endif
162
163 // Raw flash access functions
164 /*local_cmd_entry("erase",
165                 "Erase FLASH contents",
166                 "-f <flash_addr> -l <length>",
167                 fis_erase,
168                 FIS_cmds
169     );*/
170 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
171 local_cmd_entry("lock",
172                 "LOCK FLASH contents",
173                 "[-f <flash_addr> -l <length>] [name]",
174                 fis_lock,
175                 FIS_cmds
176     );
177 local_cmd_entry("unlock",
178                 "UNLOCK FLASH contents",
179                 "[-f <flash_addr> -l <length>] [name]",
180                 fis_unlock,
181                 FIS_cmds
182     );
183 #endif
184 /*local_cmd_entry("write",
185                 "Write raw data directly to FLASH",
186                 "-f <flash_addr> -b <mem_base> -l <image_length>",
187                 fis_write,
188                 FIS_cmds
189     );*/
190
191 // Define table boundaries
192 CYG_HAL_TABLE_BEGIN( __FIS_cmds_TAB__, FIS_cmds);
193 CYG_HAL_TABLE_END( __FIS_cmds_TAB_END__, FIS_cmds);
194
195 extern struct cmd __FIS_cmds_TAB__[], __FIS_cmds_TAB_END__;
196
197 // CLI function
198 static cmd_fun do_fis;
199 RedBoot_nested_cmd("fis",
200             "Manage FLASH images",
201             "{cmds}",
202             do_fis,
203             __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
204     );
205
206 // Local data used by these routines
207 void *flash_start, *flash_end;
208 int flash_block_size, flash_num_blocks;
209 #ifdef CYGOPT_REDBOOT_FIS
210 void *fis_work_block;
211 void *fis_addr;
212 int fisdir_size;  // Size of FIS directory.
213 #endif
214 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
215 extern void *cfg_base;   // Location in Flash of config data
216 extern int   cfg_size;   // Length of config data - rounded to Flash block size
217 extern struct _config *config;
218 #endif
219
220 #if   CYGNUM_FLASH_SIZE == 0x200000
221 #define VXWORKS_BOARD_CFG_DATA 0xbfde0000
222 #define VXWORKS_RADIO_CFG_DATA 0xbfdf0000
223 #define CONSOLIDATED_DATA      0xbfdf0000
224 #define END_OF_FLASH           0xbffff000
225 #elif CYGNUM_FLASH_SIZE == 0x400000
226 #define VXWORKS_BOARD_CFG_DATA 0xbffe0000
227 #define VXWORKS_RADIO_CFG_DATA 0xbfff0000
228 #define CONSOLIDATED_DATA      0xbfff0000
229 #define END_OF_FLASH           0xbffff000
230 #elif CYGNUM_FLASH_SIZE == 0x800000
231 #define VXWORKS_BOARD_CFG_DATA 0xbffe0000
232 #define VXWORKS_RADIO_CFG_DATA 0xbfff0000
233 #define CONSOLIDATED_DATA      0xbfff0000
234 #define END_OF_FLASH           0xbffff000
235 #else
236 #Warning! Currently works for only 2MB and 4MB
237 #endif // CYGNUM_FLASH_SIZE
238
239 #define HEURISTIC_SEARCH_LEN   0x60000
240 #define MAGIC_DATA             0x35333131
241
242
243 static void
244 fis_usage(char *why)
245 {
246     diag_printf("*** invalid 'fis' command: %s\n", why);
247     cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
248 }
249
250 static void       
251 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
252 {
253     diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
254     diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
255 }
256
257 #ifdef CYGOPT_REDBOOT_FIS
258
259 // fis_endian_fixup() is used to swap endianess if required.
260 //
261 static inline void fis_endian_fixup(void *addr)
262 {
263 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
264     struct fis_image_desc *p = addr;
265     int cnt = fisdir_size / sizeof(struct fis_image_desc);
266
267     while (cnt-- > 0) {
268         p->flash_base = CYG_SWAP32(p->flash_base);
269         p->mem_base = CYG_SWAP32(p->mem_base);
270         p->size = CYG_SWAP32(p->size);
271         p->entry_point = CYG_SWAP32(p->entry_point);
272         p->data_length = CYG_SWAP32(p->data_length);
273         p->desc_cksum = CYG_SWAP32(p->desc_cksum);
274         p->file_cksum = CYG_SWAP32(p->file_cksum);
275         p++;
276     }
277 #endif
278 }
279
280 void
281 fis_read_directory(void)
282 {
283     void *err_addr;
284
285     FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
286     fis_endian_fixup(fis_work_block);
287 }
288
289 struct fis_image_desc *
290 fis_lookup(char *name, int *num)
291 {
292     int i;
293     struct fis_image_desc *img;
294
295     fis_read_directory();
296
297     img = (struct fis_image_desc *)fis_work_block;
298     for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
299         if ((img->name[0] != (unsigned char)0xFF) &&
300             (strcasecmp(name, img->name) == 0)) {
301             if (num) *num = i;
302             return img;
303         }
304     }
305     return (struct fis_image_desc *)0;
306 }
307
308 void
309 fis_update_directory(void)
310 {
311     int stat;
312     void *err_addr;
313
314     fis_endian_fixup(fis_work_block);
315 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
316     memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
317     conf_endian_fixup((char *)fis_work_block+fisdir_size);
318 #endif
319 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
320     // Ensure [quietly] that the directory is unlocked before trying to update
321     flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
322 #endif
323     if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
324         diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
325     } else {
326         if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
327                                   flash_block_size, (void **)&err_addr)) != 0) {
328             diag_printf("Error writing FIS directory at %p: %s\n",
329                         err_addr, flash_errmsg(stat));
330         }
331     }
332 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
333     // Ensure [quietly] that the directory is locked after the update
334     flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
335 #endif
336     fis_endian_fixup(fis_work_block);
337 }
338 void fis_init(int argc, char *argv[],int force);
339
340 static void fis_init_comp(int argc, char *argv[])
341 {
342 fis_init(argc, argv,0);
343 }
344 void fis_init(int argc, char *argv[],int force)
345 {
346     int stat;
347     struct fis_image_desc *img;
348     void *err_addr;
349     bool full_init = false;
350     struct option_info opts[1];
351     CYG_ADDRESS redboot_flash_start;
352     unsigned long redboot_image_size;
353
354     init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG,
355               (void *)&full_init, (bool *)0, "full initialization, erases all of flash");
356     if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, ""))
357     {
358         return;
359     }
360
361     if (!force && !verify_action("About to initialize [format] FLASH image system")) {
362         diag_printf("** Aborted\n");
363         return;
364     }
365     diag_printf("*** Initialize FLASH Image System\n");
366
367
368 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
369     redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ?
370                          flash_block_size : MIN_REDBOOT_IMAGE_SIZE;
371
372     // Create a pseudo image for RedBoot
373     img = (struct fis_image_desc *)fis_work_block;
374     memset(img, 0xFF, fisdir_size);  // Start with erased data
375 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
376     memset(img, 0, sizeof(*img));
377     strcpy(img->name, "(reserved)");
378     img->flash_base = (CYG_ADDRESS)flash_start;
379     img->mem_base = (CYG_ADDRESS)flash_start;
380     img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
381     img++;
382 #endif
383     redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
384 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
385     memset(img, 0, sizeof(*img));
386     strcpy(img->name, "RedBoot");
387     img->flash_base = redboot_flash_start;
388     img->mem_base = redboot_flash_start;
389     img->size = redboot_image_size;
390     img++;
391     redboot_flash_start += redboot_image_size;
392 #endif
393 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
394 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
395     // Take care to place the POST entry at the right offset:
396     redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
397 #endif
398     memset(img, 0, sizeof(*img));
399     strcpy(img->name, "RedBoot[post]");
400     img->flash_base = redboot_flash_start;
401     img->mem_base = redboot_flash_start;
402     img->size = redboot_image_size;
403     img++;
404     redboot_flash_start += redboot_image_size;
405 #endif
406 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
407     // And a backup image
408     memset(img, 0, sizeof(*img));
409     strcpy(img->name, "RedBoot[backup]");
410     img->flash_base = redboot_flash_start;
411     img->mem_base = redboot_flash_start;
412     img->size = redboot_image_size;
413     img++;
414     redboot_flash_start += redboot_image_size;
415 #endif
416 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
417     // And a descriptor for the configuration data
418     memset(img, 0, sizeof(*img));
419     strcpy(img->name, "RedBoot config");
420     img->flash_base = (CYG_ADDRESS)cfg_base;
421     img->mem_base = (CYG_ADDRESS)cfg_base;
422     img->size = cfg_size;
423     img++;
424 #endif
425     // And a descriptor for the descriptor table itself
426     memset(img, 0, sizeof(*img));
427     strcpy(img->name, "FIS directory");
428     img->flash_base = (CYG_ADDRESS)fis_addr;
429     img->mem_base = (CYG_ADDRESS)fis_addr;
430     img->size = fisdir_size;
431     img++;
432
433 #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID
434     // FIS gets the size of a full block - note, this should be changed
435     // if support is added for multi-block FIS structures.
436     img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size);
437     // Add a footer so the FIS will be recognized by the ARM Boot
438     // Monitor as a reserved area.
439     {
440         tFooter* footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter));
441         cyg_uint32 check = 0;
442         cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p;
443         cyg_int32 count = (sizeof(tFooter) - 4) >> 2;
444
445         // Prepare footer. Try to protect all but the reserved space
446         // and the first RedBoot image (which is expected to be
447         // bootable), but fall back to just protecting the FIS if it's
448         // not at the default position in the flash.
449 #if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK)
450         footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start);
451         footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size;
452 #else
453         footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(fis_work_block);
454 #endif
455         footer_p->infoBase = NULL;
456         footer_p->signature = FLASH_FOOTER_SIGNATURE;
457         footer_p->type = TYPE_REDHAT_REDBOOT;
458
459         // and compute its checksum
460         for ( ; count > 0; count--) {
461             if (*check_ptr > ~check)
462                 check++;
463             check += *check_ptr++;
464         }
465         footer_p->checksum = ~check;
466     }
467 #endif
468
469     // Do this after creating the initialized table because that inherently
470     // calculates where the high water mark of default RedBoot images is.
471
472     if (full_init) {
473         unsigned long erase_size;
474         CYG_ADDRESS erase_start;
475         // Erase everything except default RedBoot images, fis block,
476         // and config block.
477         // First deal with the possible first part, before RedBoot images:
478 #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE)
479         erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
480         erase_size =  (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
481         if ( erase_size > erase_start ) {
482             erase_size -= erase_start;
483             if ((stat = flash_erase((void *)erase_start, erase_size,
484                                     (void **)&err_addr)) != 0) {
485                 diag_printf("   initialization failed at %p: %s\n",
486                             err_addr, flash_errmsg(stat));
487             }
488         }
489 #endif
490         // second deal with the larger part in the main:
491         erase_start = redboot_flash_start; // high water of created images
492         // Now the empty bits between the end of Redboot and the cfg and dir
493         // blocks.
494 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
495     defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \
496     !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
497         if (fis_addr > cfg_base) {
498           erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data
499         } else {
500           erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
501         }
502         if ((stat = flash_erase((void *)erase_start, erase_size,
503                                 (void **)&err_addr)) != 0) {
504           diag_printf("   initialization failed %p: %s\n",
505                  err_addr, flash_errmsg(stat));
506         }
507         erase_start += (erase_size + flash_block_size);
508         if (fis_addr > cfg_base) {
509           erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data
510         } else {
511           erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data
512         }
513         if ((stat = flash_erase((void *)erase_start, erase_size,
514                                 (void **)&err_addr)) != 0) {
515           diag_printf("   initialization failed %p: %s\n",
516                  err_addr, flash_errmsg(stat));
517         }
518         erase_start += (erase_size + flash_block_size);
519 #else  // !CYGSEM_REDBOOT_FLASH_CONFIG       
520         erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
521         if ((stat = flash_erase((void *)erase_start, erase_size,
522                                 (void **)&err_addr)) != 0) {
523           diag_printf("   initialization failed %p: %s\n",
524                  err_addr, flash_errmsg(stat));
525         }
526         erase_start += (erase_size + flash_block_size);         
527 #endif
528         // Lastly, anything at the end, if there is any
529         if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) {
530             erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
531             if ((stat = flash_erase((void *)erase_start, erase_size,
532                                     (void **)&err_addr)) != 0) {
533                 diag_printf("   initialization failed at %p: %s\n",
534                             err_addr, flash_errmsg(stat));
535             }
536         }
537 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
538     // In this case, 'fis free' works by scanning for erased blocks.  Since the
539     // "-f" option was not supplied, there may be areas which are not used but
540     // don't appear to be free since they are not erased - thus the warning
541     } else {
542         diag_printf("    Warning: device contents not erased, some blocks may not be usable\n");
543 #endif
544     }
545     fis_update_directory();
546 }
547
548 static void
549 fis_list(int argc, char *argv[])
550 {
551     struct fis_image_desc *img;
552     int i, image_indx;
553     bool show_cksums = false;
554     bool show_datalen = false;
555     struct option_info opts[2];
556     unsigned long last_addr, lowest_addr;
557     bool image_found;
558
559 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
560     // FIXME: this is somewhat half-baked
561     extern void arm_fis_list(void);
562     arm_fis_list();
563     return;
564 #endif
565
566     init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG,
567               (void *)&show_datalen, (bool *)0, "display data length");
568 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
569     init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
570               (void *)&show_cksums, (bool *)0, "display checksums");
571     i = 2;
572 #else
573     i = 1;
574 #endif
575     if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
576         return;
577     }
578     fis_read_directory();
579
580     // Let diag_printf do the formatting in both cases, rather than counting
581     // cols by hand....
582     diag_printf("%-16s  %-10s  %-10s  %-10s  %-s\n",
583                 "Name","FLASH addr",
584                 show_cksums ? "Checksum" : "Mem addr",
585                 show_datalen ? "Datalen" : "Length",
586                 "Entry point" );
587     last_addr = 0;
588     image_indx = 0;
589     do {
590         image_found = false;
591         lowest_addr = 0xFFFFFFFF;
592         img = (struct fis_image_desc *) fis_work_block;
593         for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
594             if (img->name[0] != (unsigned char)0xFF) {
595                 if ((img->flash_base > last_addr) && (img->flash_base < lowest_addr)) {
596                     lowest_addr = img->flash_base;
597                     image_found = true;
598                     image_indx = i;
599                 }
600             }
601         }
602         if (image_found) {
603             img = (struct fis_image_desc *) fis_work_block;
604             img += image_indx;
605             diag_printf("%-16s  0x%08lX  0x%08lX  0x%08lX  0x%08lX\n", img->name,
606                         img->flash_base,
607 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
608                         show_cksums ? img->file_cksum : img->mem_base,
609                         show_datalen ? img->data_length : img->size,
610 #else
611                         img->mem_base,
612                         img->size,
613 #endif
614                         img->entry_point);
615         }
616         last_addr = lowest_addr;
617     } while (image_found == true);
618 }
619
620 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
621 struct free_chunk {
622     CYG_ADDRESS start, end;
623 };
624
625 static int
626 find_free(struct free_chunk *chunks)
627 {
628     CYG_ADDRESS *fis_ptr, *fis_end;
629     struct fis_image_desc *img;
630     int i, idx;
631     int num_chunks = 1;
632
633     // Do not search the area reserved for pre-RedBoot systems:
634     fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start +
635                               CYGNUM_REDBOOT_FLASH_RESERVED_BASE +
636                               CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
637     fis_end = (CYG_ADDRESS *)flash_end;
638     chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
639     chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
640     fis_read_directory();
641     img = (struct fis_image_desc *) fis_work_block;
642     for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
643         if (img->name[0] != (unsigned char)0xFF) {
644             // Figure out which chunk this is in and split it
645             for (idx = 0;  idx < num_chunks;  idx++) {
646                 if ((img->flash_base >= chunks[idx].start) &&
647                     (img->flash_base <= chunks[idx].end)) {
648                     if (img->flash_base == chunks[idx].start) {
649                         chunks[idx].start += img->size;
650                         if (chunks[idx].start >= chunks[idx].end) {
651                             // This free chunk has collapsed
652                             while (idx < (num_chunks-1)) {
653                                 chunks[idx] = chunks[idx+1];
654                                 idx++;
655                             }
656                             num_chunks--;
657                         }
658                     } else if ((img->flash_base+img->size) == chunks[idx].end) {
659                         chunks[idx].end = img->flash_base;
660                     } else {
661                         // Split chunk into two parts
662                         if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) {
663                             chunks[idx+1].start = img->flash_base + img->size;
664                             chunks[idx+1].end = chunks[idx].end;
665                             if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
666                                 diag_printf("Warning: too many free chunks\n");
667                                 return num_chunks;
668                             }
669                         }
670                         chunks[idx].end = img->flash_base;
671                     }
672                     break;
673                 }
674             }
675         }
676     }
677     return num_chunks;
678 }
679 #endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
680
681
682 // Find the first unused area of flash which is long enough
683 static bool
684 fis_find_free(CYG_ADDRESS *addr, unsigned long length)
685 {
686 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
687     unsigned long *fis_ptr, *fis_end, flash_data;
688     unsigned long *area_start;
689     void *err_addr;
690
691     // Do not search the area reserved for pre-RedBoot systems:
692     fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start +
693                                 CYGNUM_REDBOOT_FLASH_RESERVED_BASE +
694                                 CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
695     fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
696     area_start = fis_ptr;
697     while (fis_ptr < fis_end) {
698         flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
699         if (flash_data != (unsigned long)0xFFFFFFFF) {
700             if (area_start != fis_ptr) {
701                 // Assume that this is something
702                 if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
703                     *addr = (CYG_ADDRESS)area_start;
704                     return true;
705                 }
706             }
707             // Find next blank block
708             area_start = fis_ptr;
709             while (area_start < fis_end) {
710                 flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
711                 if (flash_data == (unsigned long)0xFFFFFFFF) {
712                     break;
713                 }
714                 area_start += flash_block_size / sizeof(CYG_ADDRESS);
715             }
716             fis_ptr = area_start;
717         } else {
718             fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
719         }
720     }
721     if (area_start != fis_ptr) {
722         if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
723             *addr = (CYG_ADDRESS)area_start;
724             return true;
725         }
726     }
727     return false;
728 #else
729     struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
730     int idx, num_chunks;
731
732     num_chunks = find_free(chunks);
733     for (idx = 0;  idx < num_chunks;  idx++) {
734         if ((chunks[idx].end - chunks[idx].start) >= length) {
735             *addr = (CYG_ADDRESS)chunks[idx].start;
736             return true;
737         }
738     }
739     return false;
740 #endif
741 }
742
743 static void
744 fis_create_old(int argc, char *argv[])
745 {
746     int i, stat;
747     unsigned long length, img_size;
748     CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr;
749     char *name;
750     bool mem_addr_set = false;
751     bool exec_addr_set = false;
752     bool entry_addr_set = false;
753     bool flash_addr_set = false;
754     bool length_set = false;
755     bool img_size_set = false;
756     bool no_copy = false;
757     void *err_addr;
758     struct fis_image_desc *img = NULL;
759     bool defaults_assumed;
760     struct option_info opts[7];
761     bool prog_ok = true;
762
763     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
764               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
765     init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM,
766               (void *)&exec_addr, (bool *)&exec_addr_set, "ram base address");
767     init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,
768               (void *)&entry_addr, (bool *)&entry_addr_set, "entry point address");
769     init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM,
770               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
771     init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM,
772               (void *)&length, (bool *)&length_set, "image length [in FLASH]");
773     init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
774               (void *)&img_size, (bool *)&img_size_set, "image size [actual data]");
775     init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG,
776               (void *)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");
777     if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
778     {
779         fis_usage("invalid arguments");
780         return;
781     }
782
783     fis_read_directory();
784     defaults_assumed = false;
785     if (name) {
786         // Search existing files to acquire defaults for params not specified:
787         img = fis_lookup(name, NULL);
788         if (img) {
789             // Found it, so get image size from there
790             if (!length_set) {
791                 length_set = true;
792                 length = img->size;
793                 defaults_assumed = true;
794             }
795         }
796     }
797     if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) &&
798         (load_address_end) < (CYG_ADDRESS)ram_end) {
799         mem_addr = load_address;
800         mem_addr_set = true;
801         defaults_assumed = true;
802         // Get entry address from loader, unless overridden
803         if (!entry_addr_set)
804             entry_addr = entry_address;
805         if (!length_set) {
806             length = load_address_end - load_address;
807             length_set = true;
808         } else if (defaults_assumed && !img_size_set) {
809             /* We got length from the FIS table, so the size of the
810                actual loaded image becomes img_size */
811             img_size = load_address_end - load_address;
812             img_size_set = true;
813         }
814     }
815     // Get the remaining fall-back values from the fis
816     if (img) {
817         if (!exec_addr_set) {
818             // Preserve "normal" behaviour
819             exec_addr_set = true;
820             exec_addr = flash_addr_set ? flash_addr : mem_addr;
821         }
822         if (!flash_addr_set) {
823             flash_addr_set = true;
824             flash_addr = img->flash_base;
825             defaults_assumed = true;
826         }
827     }
828
829     if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
830         !length_set || !name) {
831         fis_usage("required parameter missing");
832         return;
833     }
834     if (!img_size_set) {
835         img_size = length;
836     }
837     // 'length' is size of FLASH image, 'img_size' is actual data size
838     // Round up length to FLASH block size
839 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
840     length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
841     if (length < img_size) {
842         diag_printf("Invalid FLASH image size/length combination\n");
843         return;
844     }
845 #endif
846     if (flash_addr_set &&
847         ((stat = flash_verify_addr((void *)flash_addr)) ||
848          (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
849         _show_invalid_flash_address(flash_addr, stat);
850         return;
851     }
852     if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) {
853         diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
854         diag_printf("   must be 0x%x aligned\n", flash_block_size);
855         return;
856     }
857     if (strlen(name) >= sizeof(img->name)) {
858         diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
859         return;
860     }
861     if (!no_copy) {
862         if ((mem_addr < (CYG_ADDRESS)ram_start) ||
863             ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) {
864             diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
865             diag_printf("   valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
866         }
867         if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
868             diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
869             return;
870         }
871     }
872     // First, see if the image by this name has agreable properties
873     if (img) {
874         if (flash_addr_set && (img->flash_base != flash_addr)) {
875             diag_printf("Image found, but flash address (%p)\n"
876                         "             is incorrect (present image location %p)\n",
877                         flash_addr, img->flash_base);
878            
879             return;
880         }
881         if (img->size != length) {
882             diag_printf("Image found, but length (0x%lx, necessitating image size 0x%lx)\n"
883                         "             is incorrect (present image size 0x%lx)\n",
884                         img_size, length, img->size);
885             return;
886         }
887         if (!verify_action("An image named '%s' exists", name)) {
888             return;
889         } else {               
890             if (defaults_assumed) {
891                 if (no_copy &&
892                     !verify_action("* CAUTION * about to program '%s'\n            at %p..%p from %p",
893                                    name, (void *)flash_addr, (void *)(flash_addr+img_size-1),
894                                    (void *)mem_addr)) {
895                     return;  // The guy gave up
896                 }
897             }
898         }
899     } else {
900 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
901         // Make sure that any FLASH address specified directly is truly free
902         if (flash_addr_set && !no_copy) {
903             struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
904             int idx, num_chunks;
905             bool is_free = false;
906
907             num_chunks = find_free(chunks);
908             for (idx = 0;  idx < num_chunks;  idx++) {
909                 if ((flash_addr >= chunks[idx].start) &&
910                     ((flash_addr+length-1) <= chunks[idx].end)) {
911                     is_free = true;
912                 }
913             }
914             if (!is_free) {
915                 diag_printf("Invalid FLASH address - not free!\n");
916                 return;
917             }
918         }
919 #endif
920         // If not image by that name, try and find an empty slot
921         img = (struct fis_image_desc *)fis_work_block;
922         for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
923             if (img->name[0] == (unsigned char)0xFF) {
924                 break;
925             }
926         }
927     }
928     if (!no_copy) {
929         // Safety check - make sure the address range is not within the code we're running
930         if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) {
931             diag_printf("Can't program this region - contains code in use!\n");
932             return;
933         }
934         if (prog_ok) {
935             // Erase area to be programmed
936             if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
937                 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
938                 prog_ok = false;
939             }
940         }
941         if (prog_ok) {
942             // Now program it
943             if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
944                 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
945                 prog_ok = false;
946             }
947         }
948     }
949     if (prog_ok) {
950         // Update directory
951         memset(img, 0, sizeof(*img));
952         strcpy(img->name, name);
953         img->flash_base = flash_addr;
954         img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr);
955         img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address;  // Hope it's been set
956         img->size = length;
957         img->data_length = img_size;
958 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
959         if (!no_copy) {
960             img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size);
961         } else {
962             // No way to compute this, sorry
963             img->file_cksum = 0;
964         }
965 #endif
966         fis_update_directory();
967     }
968 }
969
970 #if defined(CYGPKG_HAL_MIPS_AR2316)
971
972 static void
973 fis_create_accton(int argc, char *argv[])
974 {
975 *(volatile unsigned*)0xB1000090 |= 1;/*set GPIO0 to 1 to spi flash CS normal state*/
976 *(volatile unsigned*)0xB1000098 |= 1;/*set GPIO0 to be output*/                 
977 page_programming_supported = 1;
978 page_gpio = 0;
979 fis_create_old(argc,argv);
980
981 }
982 static void
983 fis_create_256(int argc, char *argv[])
984 {
985 *(volatile unsigned*)0xB1000090 |= 1<<3;/*set GPIO0 to 1 to spi flash CS normal state*/
986 *(volatile unsigned*)0xB1000098 |= 1<<3;/*set GPIO0 to be output*/             
987 page_programming_supported = 1;
988 page_gpio = 3;
989 fis_create_old(argc,argv);
990
991 }
992 #endif
993 static void
994 fis_create(int argc, char *argv[])
995 {
996 page_programming_supported = 0;
997 page_gpio = 0;
998 fis_create_old(argc,argv);
999 }
1000
1001 extern void arm_fis_delete(char *);
1002
1003 static void
1004 fis_load(int argc, char *argv[])
1005 {
1006     char *name;
1007     struct fis_image_desc *img;
1008     CYG_ADDRESS mem_addr;
1009     bool mem_addr_set = false;
1010     bool show_cksum = false;
1011     struct option_info opts[3];
1012 #if defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
1013     unsigned long cksum;
1014 #endif
1015     int num_options;
1016 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) ||  defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
1017     bool decompress = false;
1018 #endif
1019
1020 #if defined(CYGPRI_REDBOOT_7ZIP_FLASH)
1021     bool ldecompress = false;
1022 #endif
1023     void *err_addr;
1024
1025     init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1026               (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
1027     init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
1028               (void *)&show_cksum, (bool *)0, "display checksum");
1029     num_options = 2;
1030 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
1031     init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG,
1032               (void *)&decompress, 0, "decompress");
1033     num_options++;
1034 #endif
1035
1036 #ifdef CYGPRI_REDBOOT_7ZIP_FLASH
1037     init_opts(&opts[num_options], 'l', false, OPTION_ARG_TYPE_FLG,
1038               (void *)&ldecompress, 0, "lzma");
1039     num_options++;
1040 #endif
1041
1042     CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
1043
1044     if (!scan_opts(argc, argv, 2, opts, num_options, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
1045     {
1046         fis_usage("invalid arguments");
1047         return;
1048     }
1049     if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
1050         diag_printf("No image '%s' found\n", name);
1051         return;
1052     }
1053     if (!mem_addr_set) {
1054         mem_addr = img->mem_base;
1055     }
1056     // Load image from FLASH into RAM
1057 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
1058     if (!valid_address((void *)mem_addr)) {
1059         diag_printf("Not a loadable image - try using -b ADDRESS option\n");
1060         return;
1061     }
1062 #endif
1063
1064 #if defined(CYGPRI_REDBOOT_7ZIP_FLASH)
1065     if (ldecompress) {
1066        unsigned char *in_buf,*out_buf;
1067        unsigned out_buf_len,in_buf_len;
1068        int res;
1069        in_buf = (unsigned char*) img->flash_base;
1070        out_buf = (unsigned char*) mem_addr;
1071        in_buf_len = img->data_length;
1072        res = lzma_decode(in_buf,out_buf,in_buf_len,&out_buf_len);
1073        if ( res!= 0 ) {
1074           diag_printf("lzma_decode failed. res=%d\n",res);
1075        }else {
1076             diag_printf("Image loaded from %p-%p\n", out_buf,out_buf+out_buf_len);
1077        }
1078        load_address = mem_addr;
1079        load_address_end = mem_addr + out_buf_len ;
1080        fis_read_directory();
1081     } else
1082 #endif
1083
1084 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
1085     if (decompress) {
1086         int err;
1087         _pipe_t fis_load_pipe;
1088         _pipe_t* p = &fis_load_pipe;
1089         p->out_buf = (unsigned char*) mem_addr;
1090         p->out_max = p->out_size = -1;
1091         p->in_buf = (unsigned char*) img->flash_base;
1092         p->in_avail = img->data_length;
1093
1094         err = (*_dc_init)(p);
1095
1096         if (0 == err)
1097             err = (*_dc_inflate)(p);
1098
1099         // Free used resources, do final translation of
1100         // error value.
1101         err = (*_dc_close)(p, err);
1102
1103         if (0 != err && p->msg) {
1104             diag_printf("decompression error: %s\n", p->msg);
1105         } else {
1106             diag_printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
1107         }
1108
1109         // Set load address/top
1110         load_address = mem_addr;
1111         load_address_end = (unsigned long)p->out_buf;
1112
1113         // Reload fis directory
1114         fis_read_directory();
1115     } else // dangling block
1116 #endif
1117     {
1118         flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
1119
1120         // Set load address/top
1121         load_address = mem_addr;
1122         load_address_end = mem_addr + img->data_length;
1123     }
1124     entry_address = (unsigned long)img->entry_point;
1125
1126 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
1127     cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length);
1128     if (show_cksum) {
1129         diag_printf("Checksum: 0x%08lx\n", cksum);
1130     }
1131     // When decompressing, leave CRC checking to decompressor
1132     if (!decompress && !ldecompress && img->file_cksum) {
1133         if (cksum != img->file_cksum) {
1134             diag_printf("** Warning - checksum failure.  stored: 0x%08lx, computed: 0x%08lx\n",
1135                         img->file_cksum, cksum);
1136             entry_address = (unsigned long)NO_MEMORY;
1137         }
1138     }
1139 #endif
1140 }
1141 #endif // CYGOPT_REDBOOT_FIS
1142
1143
1144
1145
1146 // This is set non-zero if the FLASH subsystem has successfully been initialized
1147 int __flash_init = 0;
1148
1149 void
1150 _flash_info(void)
1151 {
1152     if (!__flash_init) return;
1153     diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n",
1154            flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
1155 }
1156
1157 bool
1158 do_flash_init(void)
1159 {
1160     int stat;
1161
1162     if (!__flash_init) {
1163         __flash_init = 1;
1164         if ((stat = flash_init(diag_printf)) != 0) {
1165             diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
1166             return false;
1167         }
1168         flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
1169         // Keep 'end' address as last valid location, to avoid wrap around problems
1170         flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
1171         flash_get_block_info(&flash_block_size, &flash_num_blocks);
1172 #ifdef CYGOPT_REDBOOT_FIS
1173         fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
1174         fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
1175 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
1176         fis_work_block = fis_zlib_common_buffer;
1177         if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
1178             diag_printf("FLASH: common buffer too small\n");
1179             return false;
1180         }
1181 # else
1182         workspace_end = (unsigned char *)(workspace_end-fisdir_size);
1183         fis_work_block = workspace_end;
1184 # endif
1185         if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
1186             fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
1187                                 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1188         } else {
1189             fis_addr = (void *)((CYG_ADDRESS)flash_start +
1190                                 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1191         }
1192         if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1193             diag_printf("FIS directory doesn't fit\n");
1194             return false;
1195         }
1196         fis_read_directory();
1197 #endif
1198     }
1199     return true;
1200 }
1201
1202 // Wrapper to avoid compiler warnings
1203 static void
1204 _do_flash_init(void)
1205 {
1206     static int init_done = 0;
1207     if (init_done) return;
1208     init_done = 1;
1209     do_flash_init();
1210 }
1211
1212 RedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);
1213
1214 static void
1215 do_fis(int argc, char *argv[])
1216 {
1217     struct cmd *cmd;
1218
1219     if (argc < 2) {
1220         fis_usage("too few arguments");
1221         return;
1222     }
1223     if (!do_flash_init()) {
1224         diag_printf("Sorry, no FLASH memory is available\n");
1225         return;
1226     }
1227     if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__,
1228                           argv[1])) != (struct cmd *)0) {
1229         (cmd->fun)(argc, argv);
1230         return;
1231     }
1232     fis_usage("unrecognized command");
1233 }
1234
1235 // EOF flash.c
Note: See TracBrowser for help on using the browser.