1 //==========================================================================
5 // RedBoot - FLASH memory support
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
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.
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
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.
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.
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.
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####
45 // Contributors: gthomas, tkoeller
50 // This code is part of RedBoot (tm).
52 //####DESCRIPTIONEND####
54 //==========================================================================
57 #include <cyg/io/flash.h>
60 #include <cyg/infra/cyg_ass.h> // assertion macros
62 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
63 // Note horrid intertwining of functions, to save precious FLASH
64 extern void conf_endian_fixup(void *p);
67 // Round a quantity up
68 #define _rup(n,s) ((((n)+(s-1))/s)*s)
70 #ifdef CYGOPT_REDBOOT_FIS
71 // Image management functions
72 local_cmd_entry("init",
73 "Initialize FLASH Image System [FIS]",
78 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
79 # define FIS_LIST_OPTS "[-c] [-d]"
81 # define FIS_LIST_OPTS "[-d]"
83 local_cmd_entry("list",
84 "Display contents of FLASH Image System [FIS]",
89 local_cmd_entry("free",
90 "Display free [available] locations within FLASH Image System [FIS]",
95 local_cmd_entry("delete",
96 "Delete an image from FLASH Image System [FIS]",
102 static char fis_load_usage[] =
103 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
106 "[-b <memory_load_address>] [-c] name";
108 local_cmd_entry("load",
109 "Load image from FLASH Image System [FIS] into RAM",
114 local_cmd_entry("create",
116 "[-b <mem_base>] [-l <image_length>] [-s <data_length>]\n"
117 " [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
123 // Raw flash access functions
124 local_cmd_entry("erase",
125 "Erase FLASH contents",
126 "-f <flash_addr> -l <length>",
130 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
131 local_cmd_entry("lock",
132 "LOCK FLASH contents",
133 "[-f <flash_addr> -l <length>] [name]",
137 local_cmd_entry("unlock",
138 "UNLOCK FLASH contents",
139 "[-f <flash_addr> -l <length>] [name]",
144 local_cmd_entry("write",
145 "Write raw data directly to FLASH",
146 "-f <flash_addr> -b <mem_base> -l <image_length>",
151 // Define table boundaries
152 CYG_HAL_TABLE_BEGIN( __FIS_cmds_TAB__, FIS_cmds);
153 CYG_HAL_TABLE_END( __FIS_cmds_TAB_END__, FIS_cmds);
155 extern struct cmd __FIS_cmds_TAB__[], __FIS_cmds_TAB_END__;
158 static cmd_fun do_fis;
159 RedBoot_nested_cmd("fis",
160 "Manage FLASH images",
163 __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
166 // Local data used by these routines
167 void *flash_start, *flash_end;
168 int flash_block_size, flash_num_blocks;
169 #ifdef CYGOPT_REDBOOT_FIS
170 void *fis_work_block;
172 int fisdir_size; // Size of FIS directory.
174 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
175 extern void *cfg_base; // Location in Flash of config data
176 extern int cfg_size; // Length of config data - rounded to Flash block size
177 extern struct _config *config;
183 diag_printf("*** invalid 'fis' command: %s\n", why);
184 cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
188 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
190 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
191 diag_printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
194 #ifdef CYGOPT_REDBOOT_FIS
196 // fis_endian_fixup() is used to swap endianess if required.
198 static inline void fis_endian_fixup(void *addr)
200 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
201 struct fis_image_desc *p = addr;
202 int cnt = fisdir_size / sizeof(struct fis_image_desc);
205 p->flash_base = CYG_SWAP32(p->flash_base);
206 p->mem_base = CYG_SWAP32(p->mem_base);
207 p->size = CYG_SWAP32(p->size);
208 p->entry_point = CYG_SWAP32(p->entry_point);
209 p->data_length = CYG_SWAP32(p->data_length);
210 p->desc_cksum = CYG_SWAP32(p->desc_cksum);
211 p->file_cksum = CYG_SWAP32(p->file_cksum);
218 fis_read_directory(void)
222 FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
223 fis_endian_fixup(fis_work_block);
226 struct fis_image_desc *
227 fis_lookup(char *name, int *num)
230 struct fis_image_desc *img;
232 fis_read_directory();
234 img = (struct fis_image_desc *)fis_work_block;
235 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
236 if ((img->name[0] != (unsigned char)0xFF) &&
237 (strcasecmp(name, img->name) == 0)) {
242 return (struct fis_image_desc *)0;
246 fis_update_directory(void)
251 fis_endian_fixup(fis_work_block);
252 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
253 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
254 conf_endian_fixup((char *)fis_work_block+fisdir_size);
256 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
257 // Ensure [quietly] that the directory is unlocked before trying to update
258 flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
260 if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
261 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
263 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
264 flash_block_size, (void **)&err_addr)) != 0) {
265 diag_printf("Error writing FIS directory at %p: %s\n",
266 err_addr, flash_errmsg(stat));
269 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
270 // Ensure [quietly] that the directory is locked after the update
271 flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
273 fis_endian_fixup(fis_work_block);
277 fis_init(int argc, char *argv[])
280 struct fis_image_desc *img;
282 bool full_init = false;
283 struct option_info opts[1];
284 CYG_ADDRESS redboot_flash_start;
285 unsigned long redboot_image_size;
287 init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG,
288 (void *)&full_init, (bool *)0, "full initialization, erases all of flash");
289 if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, ""))
294 if (!verify_action("About to initialize [format] FLASH image system")) {
295 diag_printf("** Aborted\n");
298 diag_printf("*** Initialize FLASH Image System\n");
300 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
301 redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ?
302 flash_block_size : MIN_REDBOOT_IMAGE_SIZE;
304 // Create a pseudo image for RedBoot
305 img = (struct fis_image_desc *)fis_work_block;
306 memset(img, 0xFF, fisdir_size); // Start with erased data
307 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
308 memset(img, 0, sizeof(*img));
309 strcpy(img->name, "(reserved)");
310 img->flash_base = (CYG_ADDRESS)flash_start;
311 img->mem_base = (CYG_ADDRESS)flash_start;
312 img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
315 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
316 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
317 memset(img, 0, sizeof(*img));
318 strcpy(img->name, "RedBoot");
319 img->flash_base = redboot_flash_start;
320 img->mem_base = redboot_flash_start;
321 img->size = redboot_image_size;
323 redboot_flash_start += redboot_image_size;
325 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
326 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
327 // Take care to place the POST entry at the right offset:
328 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
330 memset(img, 0, sizeof(*img));
331 strcpy(img->name, "RedBoot[post]");
332 img->flash_base = redboot_flash_start;
333 img->mem_base = redboot_flash_start;
334 img->size = redboot_image_size;
336 redboot_flash_start += redboot_image_size;
338 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
339 // And a backup image
340 memset(img, 0, sizeof(*img));
341 strcpy(img->name, "RedBoot[backup]");
342 img->flash_base = redboot_flash_start;
343 img->mem_base = redboot_flash_start;
344 img->size = redboot_image_size;
346 redboot_flash_start += redboot_image_size;
348 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
349 // And a descriptor for the configuration data
350 memset(img, 0, sizeof(*img));
351 strcpy(img->name, "RedBoot config");
352 img->flash_base = (CYG_ADDRESS)cfg_base;
353 img->mem_base = (CYG_ADDRESS)cfg_base;
354 img->size = cfg_size;
357 // And a descriptor for the descriptor table itself
358 memset(img, 0, sizeof(*img));
359 strcpy(img->name, "FIS directory");
360 img->flash_base = (CYG_ADDRESS)fis_addr;
361 img->mem_base = (CYG_ADDRESS)fis_addr;
362 img->size = fisdir_size;
365 #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID
366 // FIS gets the size of a full block - note, this should be changed
367 // if support is added for multi-block FIS structures.
368 img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size);
369 // Add a footer so the FIS will be recognized by the ARM Boot
370 // Monitor as a reserved area.
372 tFooter* footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter));
373 cyg_uint32 check = 0;
374 cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p;
375 cyg_int32 count = (sizeof(tFooter) - 4) >> 2;
377 // Prepare footer. Try to protect all but the reserved space
378 // and the first RedBoot image (which is expected to be
379 // bootable), but fall back to just protecting the FIS if it's
380 // not at the default position in the flash.
381 #if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK)
382 footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start);
383 footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size;
385 footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(fis_work_block);
387 footer_p->infoBase = NULL;
388 footer_p->signature = FLASH_FOOTER_SIGNATURE;
389 footer_p->type = TYPE_REDHAT_REDBOOT;
391 // and compute its checksum
392 for ( ; count > 0; count--) {
393 if (*check_ptr > ~check)
395 check += *check_ptr++;
397 footer_p->checksum = ~check;
401 // Do this after creating the initialized table because that inherently
402 // calculates where the high water mark of default RedBoot images is.
405 unsigned long erase_size;
406 CYG_ADDRESS erase_start;
407 // Erase everything except default RedBoot images, fis block,
409 // First deal with the possible first part, before RedBoot images:
410 #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE)
411 erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
412 erase_size = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
413 if ( erase_size > erase_start ) {
414 erase_size -= erase_start;
415 if ((stat = flash_erase((void *)erase_start, erase_size,
416 (void **)&err_addr)) != 0) {
417 diag_printf(" initialization failed at %p: %s\n",
418 err_addr, flash_errmsg(stat));
422 // second deal with the larger part in the main:
423 erase_start = redboot_flash_start; // high water of created images
424 // Now the empty bits between the end of Redboot and the cfg and dir
426 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
427 defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \
428 !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
429 if (fis_addr > cfg_base) {
430 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data
432 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
434 if ((stat = flash_erase((void *)erase_start, erase_size,
435 (void **)&err_addr)) != 0) {
436 diag_printf(" initialization failed %p: %s\n",
437 err_addr, flash_errmsg(stat));
439 erase_start += (erase_size + flash_block_size);
440 if (fis_addr > cfg_base) {
441 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data
443 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data
445 if ((stat = flash_erase((void *)erase_start, erase_size,
446 (void **)&err_addr)) != 0) {
447 diag_printf(" initialization failed %p: %s\n",
448 err_addr, flash_errmsg(stat));
450 erase_start += (erase_size + flash_block_size);
451 #else // !CYGSEM_REDBOOT_FLASH_CONFIG
452 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
453 if ((stat = flash_erase((void *)erase_start, erase_size,
454 (void **)&err_addr)) != 0) {
455 diag_printf(" initialization failed %p: %s\n",
456 err_addr, flash_errmsg(stat));
458 erase_start += (erase_size + flash_block_size);
460 // Lastly, anything at the end, if there is any
461 if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) {
462 erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
463 if ((stat = flash_erase((void *)erase_start, erase_size,
464 (void **)&err_addr)) != 0) {
465 diag_printf(" initialization failed at %p: %s\n",
466 err_addr, flash_errmsg(stat));
469 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
470 // In this case, 'fis free' works by scanning for erased blocks. Since the
471 // "-f" option was not supplied, there may be areas which are not used but
472 // don't appear to be free since they are not erased - thus the warning
474 diag_printf(" Warning: device contents not erased, some blocks may not be usable\n");
477 fis_update_directory();
481 fis_list(int argc, char *argv[])
483 struct fis_image_desc *img;
485 bool show_cksums = false;
486 bool show_datalen = false;
487 struct option_info opts[2];
488 unsigned long last_addr, lowest_addr;
491 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
492 // FIXME: this is somewhat half-baked
493 extern void arm_fis_list(void);
498 init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG,
499 (void *)&show_datalen, (bool *)0, "display data length");
500 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
501 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
502 (void *)&show_cksums, (bool *)0, "display checksums");
507 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
510 fis_read_directory();
512 // Let diag_printf do the formatting in both cases, rather than counting
514 diag_printf("%-16s %-10s %-10s %-10s %-s\n",
516 show_cksums ? "Checksum" : "Mem addr",
517 show_datalen ? "Datalen" : "Length",
523 lowest_addr = 0xFFFFFFFF;
524 img = (struct fis_image_desc *) fis_work_block;
525 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
526 if (img->name[0] != (unsigned char)0xFF) {
527 if ((img->flash_base > last_addr) && (img->flash_base < lowest_addr)) {
528 lowest_addr = img->flash_base;
535 img = (struct fis_image_desc *) fis_work_block;
537 diag_printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->name,
538 (unsigned long)img->flash_base,
539 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
540 show_cksums ? img->file_cksum : img->mem_base,
541 show_datalen ? img->data_length : img->size,
546 (unsigned long)img->entry_point);
548 last_addr = lowest_addr;
549 } while (image_found == true);
552 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
554 CYG_ADDRESS start, end;
558 find_free(struct free_chunk *chunks)
560 CYG_ADDRESS *fis_ptr, *fis_end;
561 struct fis_image_desc *img;
565 // Do not search the area reserved for pre-RedBoot systems:
566 fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start +
567 CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
568 fis_end = (CYG_ADDRESS *)flash_end;
569 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
570 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
571 fis_read_directory();
572 img = (struct fis_image_desc *) fis_work_block;
573 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
574 if (img->name[0] != (unsigned char)0xFF) {
575 // Figure out which chunk this is in and split it
576 for (idx = 0; idx < num_chunks; idx++) {
577 if ((img->flash_base >= chunks[idx].start) &&
578 (img->flash_base <= chunks[idx].end)) {
579 if (img->flash_base == chunks[idx].start) {
580 chunks[idx].start += img->size;
581 if (chunks[idx].start >= chunks[idx].end) {
582 // This free chunk has collapsed
583 while (idx < (num_chunks-1)) {
584 chunks[idx] = chunks[idx+1];
589 } else if ((img->flash_base+img->size) == chunks[idx].end) {
590 chunks[idx].end = img->flash_base;
592 // Split chunk into two parts
593 if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) {
595 // make room for new chunk
596 for (j = num_chunks; j > (idx+1); j--)
597 chunks[j] = chunks[j-1];
598 chunks[idx+1].start = img->flash_base + img->size;
599 chunks[idx+1].end = chunks[idx].end;
600 if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
601 diag_printf("Warning: too many free chunks\n");
605 chunks[idx].end = img->flash_base;
614 #endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
617 fis_free(int argc, char *argv[])
619 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
620 unsigned long *fis_ptr, *fis_end, flash_data;
621 unsigned long *area_start;
624 // Do not search the area reserved for pre-RedBoot systems:
625 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start +
626 CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
627 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
628 area_start = fis_ptr;
629 while (fis_ptr < fis_end) {
630 flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
631 if (flash_data != (unsigned long)0xFFFFFFFF) {
632 if (area_start != fis_ptr) {
633 // Assume that this is something
634 diag_printf(" 0x%08lX .. 0x%08lX\n",
635 (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
637 // Find next blank block
638 area_start = fis_ptr;
639 while (area_start < fis_end) {
640 flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
641 if (flash_data == (unsigned long)0xFFFFFFFF) {
644 area_start += flash_block_size / sizeof(CYG_ADDRESS);
646 fis_ptr = area_start;
648 fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
651 if (area_start != fis_ptr) {
652 diag_printf(" 0x%08lX .. 0x%08lX\n",
653 (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
656 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
659 num_chunks = find_free(chunks);
660 for (idx = 0; idx < num_chunks; idx++) {
661 diag_printf(" 0x%08lX .. 0x%08lX\n",
662 (unsigned long)chunks[idx].start,
663 (unsigned long)chunks[idx].end);
668 // Find the first unused area of flash which is long enough
670 fis_find_free(CYG_ADDRESS *addr, unsigned long length)
672 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
673 unsigned long *fis_ptr, *fis_end, flash_data;
674 unsigned long *area_start;
677 // Do not search the area reserved for pre-RedBoot systems:
678 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start +
679 CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
680 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
681 area_start = fis_ptr;
682 while (fis_ptr < fis_end) {
683 flash_read(fis_ptr, &flash_data, sizeof(unsigned long), (void **)&err_addr);
684 if (flash_data != (unsigned long)0xFFFFFFFF) {
685 if (area_start != fis_ptr) {
686 // Assume that this is something
687 if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
688 *addr = (CYG_ADDRESS)area_start;
692 // Find next blank block
693 area_start = fis_ptr;
694 while (area_start < fis_end) {
695 flash_read(area_start, &flash_data, sizeof(unsigned long), (void **)&err_addr);
696 if (flash_data == (unsigned long)0xFFFFFFFF) {
699 area_start += flash_block_size / sizeof(CYG_ADDRESS);
701 fis_ptr = area_start;
703 fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
706 if (area_start != fis_ptr) {
707 if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {
708 *addr = (CYG_ADDRESS)area_start;
714 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
717 num_chunks = find_free(chunks);
718 for (idx = 0; idx < num_chunks; idx++) {
719 if ((chunks[idx].end - chunks[idx].start) >= length) {
720 *addr = (CYG_ADDRESS)chunks[idx].start;
729 fis_create(int argc, char *argv[])
732 unsigned long length, img_size;
733 CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr;
735 bool mem_addr_set = false;
736 bool exec_addr_set = false;
737 bool entry_addr_set = false;
738 bool flash_addr_set = false;
739 bool length_set = false;
740 bool img_size_set = false;
741 bool no_copy = false;
743 struct fis_image_desc *img = NULL;
744 bool defaults_assumed;
745 struct option_info opts[7];
748 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
749 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
750 init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM,
751 (void *)&exec_addr, (bool *)&exec_addr_set, "ram base address");
752 init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,
753 (void *)&entry_addr, (bool *)&entry_addr_set, "entry point address");
754 init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM,
755 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
756 init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM,
757 (void *)&length, (bool *)&length_set, "image length [in FLASH]");
758 init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
759 (void *)&img_size, (bool *)&img_size_set, "image size [actual data]");
760 init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG,
761 (void *)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");
762 if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))
764 fis_usage("invalid arguments");
768 fis_read_directory();
769 defaults_assumed = false;
771 // Search existing files to acquire defaults for params not specified:
772 img = fis_lookup(name, NULL);
774 // Found it, so get image size from there
778 defaults_assumed = true;
782 if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) &&
783 (load_address_end) < (CYG_ADDRESS)ram_end) {
784 mem_addr = load_address;
786 defaults_assumed = true;
787 // Get entry address from loader, unless overridden
789 entry_addr = entry_address;
791 length = load_address_end - load_address;
793 } else if (defaults_assumed && !img_size_set) {
794 /* We got length from the FIS table, so the size of the
795 actual loaded image becomes img_size */
796 img_size = load_address_end - load_address;
800 // Get the remaining fall-back values from the fis
802 if (!exec_addr_set) {
803 // Preserve "normal" behaviour
804 exec_addr_set = true;
805 exec_addr = flash_addr_set ? flash_addr : mem_addr;
807 if (!flash_addr_set) {
808 flash_addr_set = true;
809 flash_addr = img->flash_base;
810 defaults_assumed = true;
814 if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
815 !length_set || !name) {
816 fis_usage("required parameter missing");
822 // 'length' is size of FLASH image, 'img_size' is actual data size
823 // Round up length to FLASH block size
824 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
825 length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
826 if (length < img_size) {
827 diag_printf("Invalid FLASH image size/length combination\n");
831 if (flash_addr_set &&
832 ((stat = flash_verify_addr((void *)flash_addr)) ||
833 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
834 _show_invalid_flash_address(flash_addr, stat);
837 if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) {
838 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
839 diag_printf(" must be 0x%x aligned\n", flash_block_size);
842 if (strlen(name) >= sizeof(img->name)) {
843 diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));
847 if ((mem_addr < (CYG_ADDRESS)ram_start) ||
848 ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) {
849 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
850 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
852 if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
853 diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
857 // First, see if the image by this name has agreable properties
859 if (flash_addr_set && (img->flash_base != flash_addr)) {
860 diag_printf("Image found, but flash address (%p)\n"
861 " is incorrect (present image location %p)\n",
862 (void*)flash_addr, (void*)img->flash_base);
866 if (img->size != length) {
867 diag_printf("Image found, but length (0x%lx, necessitating image size 0x%lx)\n"
868 " is incorrect (present image size 0x%lx)\n",
869 img_size, length, img->size);
872 if (!verify_action("An image named '%s' exists", name)) {
875 if (defaults_assumed) {
877 !verify_action("* CAUTION * about to program '%s'\n at %p..%p from %p",
878 name, (void *)flash_addr, (void *)(flash_addr+img_size-1),
880 return; // The guy gave up
885 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
886 // Make sure that any FLASH address specified directly is truly free
887 if (flash_addr_set && !no_copy) {
888 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
890 bool is_free = false;
892 num_chunks = find_free(chunks);
893 for (idx = 0; idx < num_chunks; idx++) {
894 if ((flash_addr >= chunks[idx].start) &&
895 ((flash_addr+length-1) <= chunks[idx].end)) {
900 diag_printf("Invalid FLASH address - not free!\n");
905 // If not image by that name, try and find an empty slot
906 img = (struct fis_image_desc *)fis_work_block;
907 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
908 if (img->name[0] == (unsigned char)0xFF) {
912 if (i >= fisdir_size/sizeof(*img)) {
913 diag_printf("Can't find an empty slot in FIS directory!\n");
918 // Safety check - make sure the address range is not within the code we're running
919 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) {
920 diag_printf("Can't program this region - contains code in use!\n");
924 // Erase area to be programmed
925 if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
926 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
932 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
933 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
940 memset(img, 0, sizeof(*img));
941 strcpy(img->name, name);
942 img->flash_base = flash_addr;
943 img->mem_base = exec_addr_set ? exec_addr : (mem_addr_set ? mem_addr : flash_addr);
944 img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set
946 img->data_length = img_size;
947 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
949 img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size);
951 // No way to compute this, sorry
955 fis_update_directory();
959 extern void arm_fis_delete(char *);
961 fis_delete(int argc, char *argv[])
964 int num_reserved, i, stat;
966 struct fis_image_desc *img;
968 if (!scan_opts(argc, argv, 2, 0, 0, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
970 fis_usage("invalid arguments");
973 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
974 // FIXME: this is somewhat half-baked
975 arm_fis_delete(name);
978 img = (struct fis_image_desc *)fis_work_block;
980 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
983 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
986 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
989 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
992 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
995 #if 1 // And the descriptor for the descriptor table itself
999 img = fis_lookup(name, &i);
1001 if (i < num_reserved) {
1002 diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->name);
1005 if (!verify_action("Delete image '%s'", name)) {
1009 diag_printf("No image '%s' found\n", name);
1012 // Erase Data blocks (free space)
1013 if ((stat = flash_erase((void *)img->flash_base, img->size, (void **)&err_addr)) != 0) {
1014 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
1016 img->name[0] = (unsigned char)0xFF;
1017 fis_update_directory();
1022 fis_load(int argc, char *argv[])
1025 struct fis_image_desc *img;
1026 CYG_ADDRESS mem_addr;
1027 bool mem_addr_set = false;
1028 bool show_cksum = false;
1029 struct option_info opts[3];
1030 #if defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
1031 unsigned long cksum;
1034 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) || defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
1035 bool decompress = false;
1039 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1040 (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address");
1041 init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,
1042 (void *)&show_cksum, (bool *)0, "display checksum");
1044 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
1045 init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG,
1046 (void *)&decompress, 0, "decompress");
1050 CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
1052 if (!scan_opts(argc, argv, 2, opts, num_options, (void *)&name, OPTION_ARG_TYPE_STR, "image name"))
1054 fis_usage("invalid arguments");
1057 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
1058 diag_printf("No image '%s' found\n", name);
1061 if (!mem_addr_set) {
1062 mem_addr = img->mem_base;
1064 // Load image from FLASH into RAM
1065 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
1066 if (!valid_address((void *)mem_addr)) {
1067 diag_printf("Not a loadable image - try using -b ADDRESS option\n");
1071 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
1074 _pipe_t fis_load_pipe;
1075 _pipe_t* p = &fis_load_pipe;
1076 p->out_buf = (unsigned char*) mem_addr;
1077 p->out_max = p->out_size = -1;
1078 p->in_buf = (unsigned char*) img->flash_base;
1079 p->in_avail = img->data_length;
1081 err = (*_dc_init)(p);
1084 err = (*_dc_inflate)(p);
1086 // Free used resources, do final translation of
1088 err = (*_dc_close)(p, err);
1090 if (0 != err && p->msg) {
1091 diag_printf("decompression error: %s\n", p->msg);
1093 diag_printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
1096 // Set load address/top
1097 load_address = mem_addr;
1098 load_address_end = (unsigned long)p->out_buf;
1100 // Reload fis directory
1101 fis_read_directory();
1102 } else // dangling block
1105 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
1107 // Set load address/top
1108 load_address = mem_addr;
1109 load_address_end = mem_addr + img->data_length;
1111 entry_address = (unsigned long)img->entry_point;
1113 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
1114 cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length);
1116 diag_printf("Checksum: 0x%08lx\n", cksum);
1118 // When decompressing, leave CRC checking to decompressor
1119 if (!decompress && img->file_cksum) {
1120 if (cksum != img->file_cksum) {
1121 diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
1122 img->file_cksum, cksum);
1123 entry_address = (unsigned long)NO_MEMORY;
1128 #endif // CYGOPT_REDBOOT_FIS
1131 fis_write(int argc, char *argv[])
1134 unsigned long length;
1135 CYG_ADDRESS mem_addr, flash_addr;
1136 bool mem_addr_set = false;
1137 bool flash_addr_set = false;
1138 bool length_set = false;
1140 struct option_info opts[3];
1143 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1144 (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
1145 init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
1146 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
1147 init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
1148 (void *)&length, (bool *)&length_set, "image length [in FLASH]");
1149 if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0))
1151 fis_usage("invalid arguments");
1155 if (!mem_addr_set || !flash_addr_set || !length_set) {
1156 fis_usage("required parameter missing");
1160 // Round up length to FLASH block size
1161 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
1162 length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
1164 if (flash_addr_set &&
1165 ((stat = flash_verify_addr((void *)flash_addr)) ||
1166 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
1167 _show_invalid_flash_address(flash_addr, stat);
1170 if (flash_addr_set && flash_addr & (flash_block_size-1)) {
1171 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
1172 diag_printf(" must be 0x%x aligned\n", flash_block_size);
1175 if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1176 ((mem_addr+length) >= (CYG_ADDRESS)ram_end)) {
1177 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
1178 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
1180 // Safety check - make sure the address range is not within the code we're running
1181 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
1182 diag_printf("Can't program this region - contains code in use!\n");
1185 if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p",
1186 (void *)flash_addr, (void *)(flash_addr+length-1),
1187 (void *)mem_addr)) {
1188 return; // The guy gave up
1192 // Erase area to be programmed
1193 if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
1194 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
1200 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
1201 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
1208 fis_erase(int argc, char *argv[])
1211 unsigned long length;
1212 CYG_ADDRESS flash_addr;
1213 bool flash_addr_set = false;
1214 bool length_set = false;
1216 struct option_info opts[2];
1218 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1219 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
1220 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1221 (void *)&length, (bool *)&length_set, "length");
1222 if (!scan_opts(argc, argv, 2, opts, 2, (void **)0, 0, ""))
1224 fis_usage("invalid arguments");
1228 if (!flash_addr_set || !length_set) {
1229 fis_usage("missing argument");
1232 if (flash_addr_set &&
1233 ((stat = flash_verify_addr((void *)flash_addr)) ||
1234 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
1235 _show_invalid_flash_address(flash_addr, stat);
1238 if (flash_addr_set && flash_addr & (flash_block_size-1)) {
1239 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
1240 diag_printf(" must be 0x%x aligned\n", flash_block_size);
1243 // Safety check - make sure the address range is not within the code we're running
1244 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
1245 diag_printf("Can't erase this region - contains code in use!\n");
1248 if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
1249 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
1253 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
1256 fis_lock(int argc, char *argv[])
1260 unsigned long length;
1261 CYG_ADDRESS flash_addr;
1262 bool flash_addr_set = false;
1263 bool length_set = false;
1265 struct option_info opts[2];
1267 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1268 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
1269 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1270 (void *)&length, (bool *)&length_set, "length");
1271 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name"))
1273 fis_usage("invalid arguments");
1277 /* Get parameters from image if specified */
1279 struct fis_image_desc *img;
1280 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
1281 diag_printf("No image '%s' found\n", name);
1285 flash_addr = img->flash_base;
1287 } else if (!flash_addr_set || !length_set) {
1288 fis_usage("missing argument");
1291 if (flash_addr_set &&
1292 ((stat = flash_verify_addr((void *)flash_addr)) ||
1293 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
1294 _show_invalid_flash_address(flash_addr, stat);
1297 if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
1298 diag_printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
1303 fis_unlock(int argc, char *argv[])
1307 unsigned long length;
1308 CYG_ADDRESS flash_addr;
1309 bool flash_addr_set = false;
1310 bool length_set = false;
1312 struct option_info opts[2];
1314 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1315 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
1316 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1317 (void *)&length, (bool *)&length_set, "length");
1318 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name"))
1320 fis_usage("invalid arguments");
1325 struct fis_image_desc *img;
1326 if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
1327 diag_printf("No image '%s' found\n", name);
1331 flash_addr = img->flash_base;
1333 } else if (!flash_addr_set || !length_set) {
1334 fis_usage("missing argument");
1337 if (flash_addr_set &&
1338 ((stat = flash_verify_addr((void *)flash_addr)) ||
1339 (stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
1340 _show_invalid_flash_address(flash_addr, stat);
1344 if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
1345 diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
1350 // This is set non-zero if the FLASH subsystem has successfully been initialized
1351 int __flash_init = 0;
1356 if (!__flash_init) return;
1357 diag_printf("FLASH: %p - 0x%x, %d blocks of %p bytes each.\n",
1358 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
1366 if (!__flash_init) {
1368 if ((stat = flash_init(diag_printf)) != 0) {
1369 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
1372 flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
1373 // Keep 'end' address as last valid location, to avoid wrap around problems
1374 flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
1375 flash_get_block_info(&flash_block_size, &flash_num_blocks);
1376 #ifdef CYGOPT_REDBOOT_FIS
1377 fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
1378 fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
1379 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
1380 fis_work_block = fis_zlib_common_buffer;
1381 if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
1382 diag_printf("FLASH: common buffer too small\n");
1386 workspace_end = (unsigned char *)(workspace_end-fisdir_size);
1387 fis_work_block = workspace_end;
1389 if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
1390 fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
1391 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1393 fis_addr = (void *)((CYG_ADDRESS)flash_start +
1394 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
1396 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1397 diag_printf("FIS directory doesn't fit\n");
1400 fis_read_directory();
1406 // Wrapper to avoid compiler warnings
1408 _do_flash_init(void)
1410 static int init_done = 0;
1411 if (init_done) return;
1416 RedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);
1419 do_fis(int argc, char *argv[])
1424 fis_usage("too few arguments");
1427 if (!do_flash_init()) {
1428 diag_printf("Sorry, no FLASH memory is available\n");
1431 if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__,
1432 argv[1])) != (struct cmd *)0) {
1433 (cmd->fun)(argc, argv);
1436 fis_usage("unrecognized command");