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

Revision 12429, 37.9 kB (checked in by BrainSlayer, 5 months ago)

compressed ELF support is required for ubnt images

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