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 #define _FLASH_PRIVATE_
58 #include <cyg/io/flash.h>
61 #include <cyg/infra/cyg_ass.h> // assertion macros
63 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
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);
73 #if defined(CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT) && defined(CYGSEM_REDBOOT_FLASH_CONFIG)
74 #include <flash_config.h>
76 #if (REDBOOT_IMAGE_SIZE != CYGBLD_REDBOOT_MIN_IMAGE_SIZE)
77 #error REDBOOT_IMAGE_SIZE != CYGBLD_REDBOOT_MIN_IMAGE_SIZE
80 RedBoot_config_option("automatic boot partition selection",
87 RedBoot_config_option("first OS boot partition",
89 "xt0_auto_OS_part_sel", true,
94 RedBoot_config_option("second OS boot partition",
96 "xt0_auto_OS_part_sel", true,
101 #endif // CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT && CYGSEM_REDBOOT_FLASH_CONFIG
103 // Round a quantity up
104 #define _rup(n,s) ((((n)+(s-1))/s)*s)
106 #ifdef CYGOPT_REDBOOT_FIS
107 // Image management functions
108 local_cmd_entry("init",
109 "Initialize FLASH Image System [FIS]",
114 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
115 # define FIS_LIST_OPTS "[-c] [-d]"
117 # define FIS_LIST_OPTS "[-d]"
119 local_cmd_entry("list",
120 "Display contents of FLASH Image System [FIS]",
125 local_cmd_entry("free",
126 "Display free [available] locations within FLASH Image System [FIS]",
131 local_cmd_entry("delete",
132 "Delete an image from FLASH Image System [FIS]",
138 static char fis_load_usage[] =
139 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
142 "[-b <memory_load_address>] [-c] "
143 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
148 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
151 "\t-c: print checksum\n"
152 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
153 "\t-w: load as Windows CE image\n"
157 local_cmd_entry("load",
158 "Load image from FLASH Image System [FIS] into RAM",
163 local_cmd_entry("create",
165 "[-b <mem_base>] [-l <image_length>] [-s <data_length>]\n"
166 " [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
172 // Raw flash access functions
173 local_cmd_entry("erase",
174 "Erase FLASH contents",
175 "-f <flash_addr> -l <length>",
179 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
180 local_cmd_entry("lock",
181 "LOCK FLASH contents",
182 "[-f <flash_addr> -l <length>] [name]",
186 local_cmd_entry("unlock",
187 "UNLOCK FLASH contents",
188 "[-f <flash_addr> -l <length>] [name]",
193 local_cmd_entry("write",
194 "Write raw data directly to FLASH",
195 "-f <flash_addr> -b <mem_base> -l <image_length>",
200 // Define table boundaries
201 CYG_HAL_TABLE_BEGIN( __FIS_cmds_TAB__, FIS_cmds);
202 CYG_HAL_TABLE_END( __FIS_cmds_TAB_END__, FIS_cmds);
204 extern struct cmd __FIS_cmds_TAB__[], __FIS_cmds_TAB_END__;
207 static cmd_fun do_fis;
208 RedBoot_nested_cmd("fis",
209 "Manage FLASH images",
212 __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
215 // Local data used by these routines
216 void *flash_start, *flash_end;
217 int flash_block_size, flash_num_blocks;
218 #ifdef CYGOPT_REDBOOT_FIS
219 void *fis_work_block;
221 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
222 void *redundant_fis_addr;
224 int fisdir_size; // Size of FIS directory.
226 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
227 extern void *cfg_base; // Location in Flash of config data
228 extern int cfg_size; // Length of config data - rounded to Flash block size
229 extern struct _config *config;
235 diag_printf("*** invalid 'fis' command: %s\n", why);
236 cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
240 _show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
242 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
243 diag_printf(" valid range is %p-%p\n", flash_start, flash_end);
246 #ifdef CYGOPT_REDBOOT_FIS
248 // fis_endian_fixup() is used to swap endianess if required.
250 static inline void fis_endian_fixup(void *addr)
252 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
253 struct fis_image_desc *p = addr;
254 int cnt = fisdir_size / sizeof(struct fis_image_desc);
257 p->flash_base = CYG_SWAP32(p->flash_base);
258 p->mem_base = CYG_SWAP32(p->mem_base);
259 p->size = CYG_SWAP32(p->size);
260 p->entry_point = CYG_SWAP32(p->entry_point);
261 p->data_length = CYG_SWAP32(p->data_length);
262 p->desc_cksum = CYG_SWAP32(p->desc_cksum);
263 p->file_cksum = CYG_SWAP32(p->file_cksum);
270 fis_read_directory(void)
274 FLASH_READ(fis_addr, fis_work_block, fisdir_size, &err_addr);
275 fis_endian_fixup(fis_work_block);
278 struct fis_image_desc *
279 fis_lookup(char *name, int *num)
282 struct fis_image_desc *img;
284 fis_read_directory();
286 img = (struct fis_image_desc *)fis_work_block;
287 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
288 if ((img->u.name[0] != 0xFF) &&
289 (strcasecmp(name, img->u.name) == 0)) {
297 int fis_start_update_directory(int autolock)
299 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
300 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
301 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
302 // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
305 int do_autolock = autolock;
309 struct fis_image_desc *img;
313 /*exchange old and new valid fis tables*/
314 tmp_fis_addr = fis_addr;
315 fis_addr = redundant_fis_addr;
316 redundant_fis_addr = tmp_fis_addr;
318 //adjust the contents of the new fis table
319 img = fis_work_block;
321 memcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC,
322 CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
323 img->u.valid_info.valid_flag[0] = CYG_REDBOOT_RFIS_IN_PROGRESS;
324 img->u.valid_info.valid_flag[1] = CYG_REDBOOT_RFIS_IN_PROGRESS;
325 img->u.valid_info.version_count = img->u.valid_info.version_count+1;
328 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
330 flash_unlock((void *)fis_addr, fisdir_size, &err_addr);
333 flash_erase(fis_addr, fisdir_size, &err_addr);
334 //now magic is 0xffffffff
335 fis_endian_fixup(fis_work_block);
336 flash_program(fis_addr, fis_work_block, flash_block_size, &err_addr);
337 fis_endian_fixup(fis_work_block);
338 //now magic is 0xff1234ff, valid is IN_PROGRESS, version_count is the old one +1
341 /* nothing to do here without redundant fis */
348 fis_update_directory(int autolock, int error)
352 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
353 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
354 // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
357 int do_autolock = autolock;
361 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
363 struct fis_image_desc *img = fis_work_block;
365 // called from invalid state
366 if (img->u.valid_info.valid_flag[0] != CYG_REDBOOT_RFIS_IN_PROGRESS)
369 //if it failed, reset is0Valid to the state before startUpdateDirectory()
370 //g_data.fisTable hasn't been changed yet, so it doesn't have to be reset now
371 //then reread the contents from flash
372 //setting the valid flag of the failed table to "INVALID" might also be not too bad
373 //but IN_PROGRESS is also good enough I think
375 void *swap_fis_addr = fis_addr;
376 fis_addr = redundant_fis_addr;
377 redundant_fis_addr = swap_fis_addr;
380 void *tmp_fis_addr = (void *)((CYG_ADDRESS)fis_addr +
381 CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
383 img->u.valid_info.valid_flag[0] = CYG_REDBOOT_RFIS_VALID;
384 img->u.valid_info.valid_flag[1] = CYG_REDBOOT_RFIS_VALID;
386 flash_program(tmp_fis_addr, img->u.valid_info.valid_flag,
387 sizeof(img->u.valid_info.valid_flag), &err_addr);
389 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
391 flash_lock((void *)fis_addr, fisdir_size, &err_addr);
394 #else // CYGOPT_REDBOOT_REDUNDANT_FIS
395 int blk_size = fisdir_size;
398 fis_endian_fixup(fis_work_block);
399 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
400 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
401 conf_endian_fixup((char *)fis_work_block+fisdir_size);
402 blk_size += cfg_size;
404 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
406 flash_unlock((void *)fis_addr, blk_size, &err_addr);
408 if ((stat = flash_erase(fis_addr, flash_block_size, &err_addr)) != 0) {
409 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
411 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
412 flash_block_size, &err_addr)) != 0) {
413 diag_printf("Error writing FIS directory at %p: %s\n",
414 err_addr, flash_errmsg(stat));
417 fis_endian_fixup(fis_work_block);
418 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
420 flash_lock((void *)fis_addr, blk_size, &err_addr);
423 #endif // CYGOPT_REDBOOT_REDUNDANT_FIS
428 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
431 fis_get_valid_buf(struct fis_image_desc *img0, struct fis_image_desc *img1, int *update_was_interrupted)
433 *update_was_interrupted = 0;
434 if (strncmp(img1->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC,
435 CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH) != 0) {
437 if (img0->u.valid_info.version_count > 0) {
438 *update_was_interrupted = 1;
441 } else if (strncmp(img0->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC,
442 CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH) != 0) {
444 if (img1->u.valid_info.version_count > 0) {
445 *update_was_interrupted = 1;
449 //magic is ok for both, now check the valid flag
450 if ((img1->u.valid_info.valid_flag[0] != CYG_REDBOOT_RFIS_VALID) ||
451 (img1->u.valid_info.valid_flag[1] != CYG_REDBOOT_RFIS_VALID)) {
453 *update_was_interrupted = 1;
455 } else if ((img0->u.valid_info.valid_flag[0] != CYG_REDBOOT_RFIS_VALID) ||
456 (img0->u.valid_info.valid_flag[1] != CYG_REDBOOT_RFIS_VALID)) {
458 *update_was_interrupted = 1;
462 //now check the version
463 return img1->u.valid_info.version_count == (img0->u.valid_info.version_count + 1);
467 fis_erase_redundant_directory(void)
472 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
473 // Ensure [quietly] that the directory is unlocked before trying
475 flash_unlock((void *)redundant_fis_addr, fisdir_size,
478 if ((stat = flash_erase(redundant_fis_addr, fisdir_size,
480 diag_printf("Error erasing FIS directory at %p: %s\n",
481 err_addr, flash_errmsg(stat));
483 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
484 // Ensure [quietly] that the directory is locked after the update
485 flash_lock((void *)redundant_fis_addr, fisdir_size, &err_addr);
491 fis_init(int argc, char *argv[])
494 struct fis_image_desc *img;
496 bool full_init = false;
497 struct option_info opts[1];
498 CYG_ADDRESS redboot_flash_start;
499 unsigned long redboot_image_size;
501 init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG,
502 &full_init, NULL, "full initialization, erases all of flash");
503 if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, "")) {
507 if (!verify_action("About to initialize [format] FLASH image system")) {
508 diag_printf("** Aborted\n");
511 diag_printf("*** Initialize FLASH Image System\n");
513 #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE
514 redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ?
515 flash_block_size : MIN_REDBOOT_IMAGE_SIZE;
517 img = fis_work_block;
518 memset(img, 0xFF, fisdir_size); // Start with erased data
520 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
521 //create the valid flag entry
522 memset(img, 0, sizeof(struct fis_image_desc));
523 strcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC);
524 img->u.valid_info.valid_flag[0] = CYG_REDBOOT_RFIS_VALID;
525 img->u.valid_info.valid_flag[1] = CYG_REDBOOT_RFIS_VALID;
526 img->u.valid_info.version_count = 0;
530 // Create a pseudo image for RedBoot
531 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
532 memset(img, 0, sizeof(*img));
533 strcpy(img->u.name, "(reserved)");
534 img->flash_base = (CYG_ADDRESS)flash_start;
535 img->mem_base = (CYG_ADDRESS)flash_start;
536 img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
539 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
540 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
541 memset(img, 0, sizeof(*img));
542 strcpy(img->u.name, "RedBoot");
543 img->flash_base = redboot_flash_start;
544 img->mem_base = redboot_flash_start;
545 img->size = redboot_image_size;
547 redboot_flash_start += redboot_image_size;
549 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
550 #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET
551 // Take care to place the POST entry at the right offset:
552 redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET;
554 memset(img, 0, sizeof(*img));
555 strcpy(img->u.name, "RedBoot[post]");
556 img->flash_base = redboot_flash_start;
557 img->mem_base = redboot_flash_start;
558 img->size = redboot_image_size;
560 redboot_flash_start += redboot_image_size;
562 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
563 // And a backup image
564 memset(img, 0, sizeof(*img));
565 strcpy(img->u.name, "RedBoot[backup]");
566 img->flash_base = redboot_flash_start;
567 img->mem_base = redboot_flash_start;
568 img->size = redboot_image_size;
570 redboot_flash_start += redboot_image_size;
572 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
573 // And a descriptor for the configuration data
574 memset(img, 0, sizeof(*img));
575 strcpy(img->u.name, "RedBoot config");
576 img->flash_base = (CYG_ADDRESS)cfg_base;
577 img->mem_base = (CYG_ADDRESS)cfg_base;
578 img->size = cfg_size;
581 // And a descriptor for the descriptor table itself
582 memset(img, 0, sizeof(*img));
583 strcpy(img->u.name, "FIS directory");
584 img->flash_base = (CYG_ADDRESS)fis_addr;
585 img->mem_base = (CYG_ADDRESS)fis_addr;
586 img->size = fisdir_size;
589 //create the entry for the redundant fis table
590 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
591 memset(img, 0, sizeof(*img));
592 strcpy(img->u.name, "Redundant FIS");
593 img->flash_base = (CYG_ADDRESS)redundant_fis_addr;
594 img->mem_base = (CYG_ADDRESS)redundant_fis_addr;
595 img->size = fisdir_size;
599 #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID
600 // FIS gets the size of a full block - note, this should be changed
601 // if support is added for multi-block FIS structures.
602 img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size);
603 // Add a footer so the FIS will be recognized by the ARM Boot
604 // Monitor as a reserved area.
606 tFooter *footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter));
607 cyg_uint32 check = 0;
608 cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p;
609 cyg_int32 count = (sizeof(tFooter) - 4) >> 2;
611 // Prepare footer. Try to protect all but the reserved space
612 // and the first RedBoot image (which is expected to be
613 // bootable), but fall back to just protecting the FIS if it's
614 // not at the default position in the flash.
615 #if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK)
616 footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start);
617 footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size;
619 footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(fis_work_block);
621 footer_p->infoBase = NULL;
622 footer_p->signature = FLASH_FOOTER_SIGNATURE;
623 footer_p->type = TYPE_REDHAT_REDBOOT;
625 // and compute its checksum
626 for ( ; count > 0; count--) {
627 if (*check_ptr > ~check)
629 check += *check_ptr++;
631 footer_p->checksum = ~check;
635 // Do this after creating the initialized table because that inherently
636 // calculates where the high water mark of default RedBoot images is.
639 unsigned long erase_size;
640 CYG_ADDRESS erase_start;
641 // Erase everything except default RedBoot images, fis block,
643 // First deal with the possible first part, before RedBoot images:
644 #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE)
645 erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;
646 erase_size = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;
647 if ( erase_size > erase_start ) {
648 erase_size -= erase_start;
649 if ((stat = flash_erase((void *)erase_start, erase_size,
651 diag_printf(" initialization failed at %p: %s\n",
652 err_addr, flash_errmsg(stat));
656 // second deal with the larger part in the main:
657 erase_start = redboot_flash_start; // high water of created images
658 // Now the empty bits between the end of Redboot and the cfg and dir
660 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \
661 defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \
662 !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)
663 if (fis_addr > cfg_base) {
664 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data
666 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
668 if ((stat = flash_erase((void *)erase_start, erase_size,
670 diag_printf(" initialization failed %p: %s\n",
671 err_addr, flash_errmsg(stat));
673 erase_start += erase_size + flash_block_size;
674 if (fis_addr > cfg_base) {
675 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data
677 erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data
679 if ((stat = flash_erase((void *)erase_start, erase_size,
681 diag_printf(" initialization failed %p: %s\n",
682 err_addr, flash_errmsg(stat));
684 erase_start += erase_size + flash_block_size;
685 #else // !CYGSEM_REDBOOT_FLASH_CONFIG
686 erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data
687 if ((stat = flash_erase((void *)erase_start, erase_size,
689 diag_printf(" initialization failed %p: %s\n",
690 err_addr, flash_errmsg(stat));
692 erase_start += erase_size + flash_block_size;
694 // Lastly, anything at the end, if there is any
695 if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) {
696 erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;
697 if ((stat = flash_erase((void *)erase_start, erase_size,
699 diag_printf(" initialization failed at %p: %s\n",
700 err_addr, flash_errmsg(stat));
703 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
704 // In this case, 'fis free' works by scanning for erased blocks. Since the
705 // "-f" option was not supplied, there may be areas which are not used but
706 // don't appear to be free since they are not erased - thus the warning
708 diag_printf(" Warning: device contents not erased, some blocks may not be usable\n");
711 fis_start_update_directory(0);
712 fis_update_directory(0, 0);
713 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
714 fis_erase_redundant_directory();
719 fis_list(int argc, char *argv[])
721 struct fis_image_desc *img;
722 int i = 0, image_indx;
723 bool show_cksums = false;
724 bool show_datalen = false;
725 struct option_info opts[2];
726 unsigned long last_addr, lowest_addr;
729 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
730 // FIXME: this is somewhat half-baked
731 extern void arm_fis_list(void);
736 init_opts(&opts[i++], 'd', false, OPTION_ARG_TYPE_FLG,
737 &show_datalen, NULL, "display data length");
738 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
739 init_opts(&opts[i++], 'c', false, OPTION_ARG_TYPE_FLG,
740 &show_cksums, NULL, "display checksums");
742 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
745 fis_read_directory();
747 // Let diag_printf do the formatting in both cases, rather than counting
749 diag_printf("%-16s %-10s %-10s %-10s %-s\n",
751 show_cksums ? "Checksum" : "Mem addr",
752 show_datalen ? "Datalen" : "Length",
758 lowest_addr = 0xFFFFFFFF;
759 img = fis_work_block;
760 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
761 if (img->u.name[0] != 0xFF) {
762 if ((img->flash_base >= last_addr) && (img->flash_base < lowest_addr)) {
763 lowest_addr = img->flash_base;
770 img = fis_work_block;
772 diag_printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->u.name,
773 (unsigned long)img->flash_base,
774 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
775 show_cksums ? img->file_cksum : (unsigned long)img->mem_base,
776 show_datalen ? img->data_length : img->size,
778 (unsigned long)img->mem_base,
781 (unsigned long)img->entry_point);
783 last_addr = lowest_addr + 1;
784 } while (image_found == true);
787 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
789 CYG_ADDRESS start, end;
793 find_free(struct free_chunk *chunks)
795 CYG_ADDRESS *fis_ptr, *fis_end;
796 struct fis_image_desc *img;
800 // Do not search the area reserved for pre-RedBoot systems:
801 fis_ptr = (CYG_ADDRESS *)((CYG_ADDRESS)flash_start +
802 CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
803 fis_end = (CYG_ADDRESS *)flash_end;
804 chunks[num_chunks - 1].start = (CYG_ADDRESS)fis_ptr;
805 chunks[num_chunks - 1].end = (CYG_ADDRESS)fis_end;
806 fis_read_directory();
807 img = fis_work_block;
808 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
809 if (img->u.name[0] != 0xFF) {
810 // Figure out which chunk this is in and split it
811 for (idx = 0; idx < num_chunks; idx++) {
812 if ((img->flash_base >= chunks[idx].start) &&
813 (img->flash_base <= chunks[idx].end)) {
814 if (img->flash_base == chunks[idx].start) {
815 chunks[idx].start += img->size;
816 if (chunks[idx].start >= chunks[idx].end) {
817 // This free chunk has collapsed
818 while (idx < (num_chunks-1)) {
819 chunks[idx] = chunks[idx+1];
824 } else if ((img->flash_base+img->size) == chunks[idx].end) {
825 chunks[idx].end = img->flash_base;
827 // Split chunk into two parts
828 if ((img->flash_base+img->size) < (CYG_ADDRESS)fis_end) {
830 // make room for new chunk
831 for (j = num_chunks; j > idx + 1; j--)
832 chunks[j] = chunks[j-1];
833 chunks[idx+1].start = img->flash_base + img->size;
834 chunks[idx+1].end = chunks[idx].end;
835 if (++num_chunks == CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS) {
836 diag_printf("Warning: too many free chunks\n");
840 chunks[idx].end = img->flash_base;
849 #endif // CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
852 fis_free(int argc, char *argv[])
854 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
855 unsigned long *fis_ptr, *fis_end, flash_data;
856 unsigned long *area_start;
859 FLASH_Enable(flash_start, flash_end);
860 // Do not search the area reserved for pre-RedBoot systems:
861 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start +
862 CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
863 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
864 area_start = fis_ptr;
865 while (fis_ptr < fis_end) {
866 flash_read(fis_ptr, &flash_data, sizeof(unsigned long), &err_addr);
867 if (flash_data != 0xFFFFFFFF) {
868 if (area_start != fis_ptr) {
869 // Assume that this is something
870 diag_printf(" 0x%08x .. 0x%08x\n",
871 (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
873 // Find next blank block
874 area_start = fis_ptr;
875 while (area_start < fis_end) {
876 flash_read(area_start, &flash_data, sizeof(unsigned long), &err_addr);
877 if (flash_data == 0xFFFFFFFF) {
880 area_start += flash_block_size / sizeof(CYG_ADDRESS);
882 fis_ptr = area_start;
884 fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
887 if (area_start != fis_ptr) {
888 diag_printf(" 0x%08x .. 0x%08x\n",
889 (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);
891 FLASH_Disable(flash_start, flash_end);
893 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
896 num_chunks = find_free(chunks);
897 for (idx = 0; idx < num_chunks; idx++) {
898 diag_printf(" 0x%08x .. 0x%08x\n",
905 // Find the first unused area of flash which is long enough
907 fis_find_free(CYG_ADDRESS *addr, unsigned long length)
909 #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
910 unsigned long *fis_ptr, *fis_end, flash_data;
911 unsigned long *area_start;
914 // Do not search the area reserved for pre-RedBoot systems:
915 fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start +
916 CYGNUM_REDBOOT_FLASH_RESERVED_BASE);
917 fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;
918 FLASH_Enable(fis_ptr, fis_end);
919 area_start = fis_ptr;
920 while (fis_ptr < fis_end) {
921 flash_read(fis_ptr, &flash_data, sizeof(unsigned long), &err_addr);
922 if (flash_data != 0xFFFFFFFF) {
923 if (area_start != fis_ptr) {
924 // Assume that this is something
925 if ((fis_ptr - area_start) >= (length / sizeof(unsigned))) {
926 *addr = (CYG_ADDRESS)area_start;
930 // Find next blank block
931 area_start = fis_ptr;
932 while (area_start < fis_end) {
933 flash_read(area_start, &flash_data, sizeof(unsigned long), &err_addr);
934 if (flash_data == 0xFFFFFFFF) {
937 area_start += flash_block_size / sizeof(CYG_ADDRESS);
939 fis_ptr = area_start;
941 fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);
944 FLASH_Disable((void *)((CYG_ADDRESS)flash_start +
945 CYGNUM_REDBOOT_FLASH_RESERVED_BASE), fis_end);
946 if (area_start != fis_ptr) {
947 if (fis_ptr - area_start >= length / sizeof(unsigned)) {
948 *addr = (CYG_ADDRESS)area_start;
954 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
957 num_chunks = find_free(chunks);
958 for (idx = 0; idx < num_chunks; idx++) {
959 if (chunks[idx].end + 1 - chunks[idx].start >= length) {
960 *addr = (CYG_ADDRESS)chunks[idx].start;
969 fis_create(int argc, char *argv[])
972 unsigned long length, img_size;
973 CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr;
975 bool mem_addr_set = false;
976 bool exec_addr_set = false;
977 bool entry_addr_set = false;
978 bool flash_addr_set = false;
979 bool length_set = false;
980 bool img_size_set = false;
981 bool no_copy = false;
983 struct fis_image_desc *img = NULL;
984 bool defaults_assumed;
985 struct option_info opts[7];
988 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
989 &mem_addr, &mem_addr_set, "memory base address");
990 init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM,
991 &exec_addr, &exec_addr_set, "ram base address");
992 init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,
993 &entry_addr, &entry_addr_set, "entry point address");
994 init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM,
995 &flash_addr, &flash_addr_set, "FLASH memory base address");
996 init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM,
997 &length, &length_set, "image length [in FLASH]");
998 init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,
999 &img_size, &img_size_set, "image size [actual data]");
1000 init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG,
1001 &no_copy, NULL, "don't copy from RAM to FLASH, just update directory");
1002 if (!scan_opts(argc, argv, 2, opts, 7, &name, OPTION_ARG_TYPE_STR, "file name")) {
1003 fis_usage("invalid arguments");
1007 fis_read_directory();
1008 defaults_assumed = false;
1010 // Search existing files to acquire defaults for params not specified:
1011 img = fis_lookup(name, NULL);
1013 // Found it, so get image size from there
1017 defaults_assumed = true;
1021 if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) &&
1022 (load_address_end) < (CYG_ADDRESS)ram_end) {
1023 mem_addr = load_address;
1024 mem_addr_set = true;
1025 defaults_assumed = true;
1026 // Get entry address from loader, unless overridden
1027 if (!entry_addr_set)
1028 entry_addr = entry_address;
1030 length = load_address_end - load_address;
1032 } else if (defaults_assumed && !img_size_set) {
1033 /* We got length from the FIS table, so the size of the
1034 actual loaded image becomes img_size */
1035 img_size = load_address_end - load_address;
1036 img_size_set = true;
1039 // Get the remaining fall-back values from the fis
1041 if (!exec_addr_set) {
1042 // Preserve "normal" behaviour
1043 exec_addr_set = true;
1044 exec_addr = flash_addr_set ? flash_addr : mem_addr;
1046 if (!flash_addr_set) {
1047 flash_addr_set = true;
1048 flash_addr = img->flash_base;
1049 defaults_assumed = true;
1053 if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||
1054 !length_set || !name) {
1055 fis_usage("required parameter missing");
1058 if (!img_size_set) {
1061 // 'length' is size of FLASH image, 'img_size' is actual data size
1062 // Round up length to FLASH block size
1063 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
1064 length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
1065 if (length < img_size) {
1066 diag_printf("Invalid FLASH image size/length combination\n");
1070 if (flash_addr_set &&
1071 ((stat = flash_verify_addr((void *)flash_addr)) ||
1072 (stat = flash_verify_addr((void *)(flash_addr + length - 1))))) {
1073 _show_invalid_flash_address(flash_addr, stat);
1076 if (flash_addr_set && ((flash_addr & (flash_block_size - 1)) != 0)) {
1077 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
1078 diag_printf(" must be 0x%x aligned\n", flash_block_size);
1081 if (strlen(name) >= sizeof(img->u.name)) {
1082 diag_printf("Name is too long, must be less than %d chars\n",
1083 sizeof(img->u.name));
1087 if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1088 ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) {
1089 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
1090 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
1092 if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {
1093 diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);
1097 // First, see if the image by this name has agreable properties
1099 if (flash_addr_set && (img->flash_base != flash_addr)) {
1100 diag_printf("Image found, but flash address (%p)\n"
1101 " is incorrect (present image location %p)\n",
1102 (void *)flash_addr, (void *)img->flash_base);
1106 if (img->size != length) {
1107 diag_printf("Image found, but length (0x%lx, necessitating image size 0x%lx)\n"
1108 " is incorrect (present image size 0x%lx)\n",
1109 img_size, length, img->size);
1112 if (!verify_action("An image named '%s' exists", name)) {
1115 if (defaults_assumed) {
1117 !verify_action("* CAUTION * about to program '%s'\n at %p..%p from %p",
1118 name, (void *)flash_addr,
1119 (void *)(flash_addr + img_size - 1),
1120 (void *)mem_addr)) {
1121 return; // The guy gave up
1126 #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS
1127 // Make sure that any FLASH address specified directly is truly free
1128 if (flash_addr_set && !no_copy) {
1129 struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS];
1130 int idx, num_chunks;
1131 bool is_free = false;
1133 num_chunks = find_free(chunks);
1134 for (idx = 0; idx < num_chunks; idx++) {
1135 if ((flash_addr >= chunks[idx].start) &&
1136 ((flash_addr + length - 1) <= chunks[idx].end)) {
1141 diag_printf("Invalid FLASH address - not free!\n");
1146 // If not image by that name, try and find an empty slot
1147 img = fis_work_block;
1148 for (i = 0; i < fisdir_size / sizeof(*img); i++, img++) {
1149 if (img->u.name[0] == 0xFF) {
1153 if (i >= fisdir_size / sizeof(*img)) {
1154 diag_printf("Can't find an empty slot in FIS directory!\n");
1159 // Safety check - make sure the address range is not within the code we're running
1160 if (flash_code_overlaps((void *)flash_addr,
1161 (void *)(flash_addr + img_size - 1))) {
1162 diag_printf("Can't program this region - contains code in use!\n");
1166 FLASH_Enable((void *)flash_addr, (void *)(flash_addr + length));
1167 // Erase area to be programmed
1168 stat = flash_erase((void *)flash_addr, length, &err_addr);
1169 FLASH_Disable((void *)flash_addr, (void *)(flash_addr + length));
1171 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
1177 FLASH_Enable((void *)flash_addr, (void *)(flash_addr + length));
1178 stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr,
1179 img_size, &err_addr);
1180 FLASH_Disable((void *)flash_addr, (void *)(flash_addr + length));
1182 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
1189 memset(img, 0, sizeof(*img));
1190 strcpy(img->u.name, name);
1191 img->flash_base = flash_addr;
1192 img->mem_base = exec_addr_set ? exec_addr : (mem_addr_set ? mem_addr : flash_addr);
1193 img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set
1195 img->data_length = img_size;
1196 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
1198 img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size);
1200 // No way to compute this, sorry
1201 img->file_cksum = 0;
1204 fis_start_update_directory(0);
1205 fis_update_directory(0, 0);
1209 extern void arm_fis_delete(char *);
1211 fis_delete(int argc, char *argv[])
1214 int num_reserved, i, stat;
1216 struct fis_image_desc *img;
1218 if (!scan_opts(argc, argv, 2, 0, 0, &name, OPTION_ARG_TYPE_STR, "image name")) {
1219 fis_usage("invalid arguments");
1222 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
1223 // FIXME: this is somewhat half-baked
1224 arm_fis_delete(name);
1227 img = (struct fis_image_desc *)fis_work_block;
1229 #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE
1232 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT
1235 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP
1238 #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST
1241 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH)
1244 #if 1 // And the descriptor for the descriptor table itself
1248 img = fis_lookup(name, &i);
1250 if (i < num_reserved) {
1251 diag_printf("Sorry, '%s' is a reserved image and cannot be deleted\n", img->u.name);
1254 if (!verify_action("Delete image '%s'", name)) {
1258 diag_printf("No image '%s' found\n", name);
1261 // Erase Data blocks (free space)
1262 if ((stat = flash_erase((void *)img->flash_base, img->size, &err_addr)) != 0) {
1263 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
1265 img->u.name[0] = 0xFF;
1266 fis_start_update_directory(0);
1267 fis_update_directory(0, 0);
1271 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
1272 static bool load_ce_img(struct fis_image_desc *img)
1276 FLASH_Enable((void *)img->flash_base, (void *)(img->flash_base + img->size));
1277 if (!ce_is_bin_image((void *)img->flash_base, img->size)) {
1278 diag_printf("** Error: This does not seem to be a valid Windows CE image\n");
1282 if (!ce_bin_load((void *)img->flash_base, img->size)) {
1283 diag_printf("** Error: Failed to load Windows CE image\n");
1287 FLASH_Disable((void *)img->flash_base, (void *)(img->flash_base + img->size));
1291 static void store_boot_img_name(char *image_name)
1294 ce_std_driver_globals *std_drv_glb = &_KARO_CECFG_START;
1296 strncpy(std_drv_glb->chBootPartition, image_name, sizeof(std_drv_glb->chBootPartition));
1298 std_drv_glb->chBootPartition[15] = '\0';
1303 fis_load(int argc, char *argv[])
1306 struct fis_image_desc *img = NULL;
1307 CYG_ADDRESS mem_addr;
1308 bool mem_addr_set = false;
1309 bool show_cksum = false;
1310 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
1311 bool load_ce = false;
1315 bool auto_part_name = false;
1316 struct option_info opts[4];
1317 #if defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
1318 unsigned long cksum;
1320 int num_options = 0;
1321 #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) || defined(CYGSEM_REDBOOT_FIS_CRC_CHECK)
1322 bool decompress = false;
1326 init_opts(&opts[num_options++], 'b', true, OPTION_ARG_TYPE_NUM,
1327 &mem_addr, &mem_addr_set, "memory [load] base address");
1328 init_opts(&opts[num_options++], 'c', false, OPTION_ARG_TYPE_FLG,
1329 &show_cksum, NULL, "display checksum");
1330 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
1331 init_opts(&opts[num_options++], 'w', false, OPTION_ARG_TYPE_FLG,
1332 &load_ce, NULL, "parse as Windows CE image");
1334 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
1335 init_opts(&opts[num_options++], 'd', false, OPTION_ARG_TYPE_FLG,
1336 &decompress, 0, "decompress");
1339 CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options");
1341 if (!scan_opts(argc, argv, 2, opts, num_options, &name,
1342 OPTION_ARG_TYPE_STR, "image name")) {
1343 fis_usage("invalid arguments");
1347 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
1348 // check if the name of the OS partition should be chosen automatically
1350 if (!flash_get_config("xt0_auto_OS_part_sel", &auto_part_name, CONFIG_BOOL)) {
1351 diag_printf("fconfig variable 'xt0_auto_OS_part_sel' not found; use 'fconfig -i' to create it\n");
1357 if ((img = fis_lookup(name, NULL)) == NULL) {
1358 if (!auto_part_name) {
1359 diag_printf("No image '%s' found\n", name);
1363 if (!mem_addr_set && !load_ce) {
1364 mem_addr = img->mem_base;
1368 // Load image from FLASH into RAM
1369 #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS
1370 // this does not make sense for WINCE as the load address is stored in the descriptor
1371 // inside the image itself. It does not matter what load address is specified in the FIS directory
1372 if (!load_ce && !valid_address((void *)mem_addr)) {
1373 diag_printf("Not a loadable image - try using -b ADDRESS option\n");
1377 #ifdef CYGBLD_BUILD_REDBOOT_WITH_WINCE_SUPPORT
1380 diag_printf("Warning: -b argument ignored for Windows CE image\n");
1382 if (!auto_part_name) {
1383 if (!load_ce_img(img))
1386 if (!img || !load_ce_img(img)) {
1387 // try the first OS image
1388 if (!flash_get_config("xt1_first_OS_part", &name, CONFIG_STRING)) {
1389 diag_printf("fconfig variable 'xt1_first_OS_part' not found; use 'fconfig -i' to create it\n");
1392 if ((img = fis_lookup(name, NULL)) == NULL) {
1393 diag_printf("No image '%s' found\n", name);
1395 diag_printf("loading WINCE OS from partition '%s'\n", name);
1398 if (!img || !load_ce_img(img)) {
1399 if (!flash_get_config("xt2_second_OS_part", &name, CONFIG_STRING)) {
1400 diag_printf("fconfig variable 'xt2_second_OS_part' not found; use 'fconfig -i' to create it\n");
1403 if ((img = fis_lookup(name, NULL)) == NULL) {
1404 diag_printf("No image '%s' found\n", name);
1407 diag_printf("loading WINCE OS from partition '%s'\n", name);
1409 if (!load_ce_img(img))
1413 store_boot_img_name(name);
1415 // Set load address/top
1416 load_address = mem_addr;
1417 load_address_end = mem_addr + img->data_length;
1421 #ifdef CYGPRI_REDBOOT_ZLIB_FLASH
1424 _pipe_t fis_load_pipe;
1425 _pipe_t *p = &fis_load_pipe;
1426 p->out_buf = (unsigned char*) mem_addr;
1427 p->out_max = p->out_size = -1;
1428 p->in_buf = (unsigned char*) img->flash_base;
1429 p->in_avail = img->data_length;
1431 err = (*_dc_init)(p);
1434 err = (*_dc_inflate)(p);
1436 // Free used resources, do final translation of
1438 err = (*_dc_close)(p, err);
1440 if (0 != err && p->msg) {
1441 diag_printf("decompression error: %s\n", p->msg);
1443 diag_printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf);
1446 // Set load address/top
1447 load_address = mem_addr;
1448 load_address_end = (unsigned long)p->out_buf;
1450 // Reload fis directory
1451 fis_read_directory();
1452 } else // dangling block
1457 FLASH_Enable((void *)img->flash_base, (void *)(img->flash_base + img->size));
1458 err = flash_read((void *)img->flash_base, (void *)mem_addr,
1459 img->data_length, &err_addr);
1460 FLASH_Disable((void *)img->flash_base, (void *)(img->flash_base + img->size));
1461 if (err != FLASH_ERR_OK) {
1462 diag_printf("** Error: Failed to load image from flash\n");
1466 // Set load address/top
1467 load_address = mem_addr;
1468 load_address_end = mem_addr + img->data_length;
1470 entry_address = (unsigned long)img->entry_point;
1472 #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
1473 cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length);
1475 diag_printf("Checksum: 0x%08lx\n", cksum);
1477 // When decompressing, leave CRC checking to decompressor
1478 if (!decompress && img->file_cksum) {
1479 if (cksum != img->file_cksum) {
1480 diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
1481 img->file_cksum, cksum);
1482 entry_address = (unsigned long)NO_MEMORY;
1486 diag_printf("image loaded 0x%08lx-0x%08lx, assumed entry at 0x%08lx\n",
1487 load_address, load_address_end - 1, entry_address);
1489 #endif // CYGOPT_REDBOOT_FIS
1492 fis_write(int argc, char *argv[])
1495 unsigned long length;
1496 CYG_ADDRESS mem_addr, flash_addr;
1497 bool mem_addr_set = false;
1498 bool flash_addr_set = false;
1499 bool length_set = false;
1501 struct option_info opts[3];
1504 init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
1505 &mem_addr, &mem_addr_set, "memory base address");
1506 init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
1507 &flash_addr, &flash_addr_set, "FLASH memory base address");
1508 init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
1509 &length, &length_set, "image length [in FLASH]");
1510 if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0))
1512 fis_usage("invalid arguments");
1516 if (!mem_addr_set || !flash_addr_set || !length_set) {
1517 fis_usage("required parameter missing");
1521 // Round up length to FLASH block size
1522 #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
1523 length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
1525 if (flash_addr_set &&
1526 ((stat = flash_verify_addr((void *)flash_addr)) ||
1527 (stat = flash_verify_addr((void *)(flash_addr + length - 1))))) {
1528 _show_invalid_flash_address(flash_addr, stat);
1531 if (flash_addr_set && flash_addr & (flash_block_size-1)) {
1532 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
1533 diag_printf(" must be 0x%x aligned\n", flash_block_size);
1536 if ((mem_addr < (CYG_ADDRESS)ram_start) ||
1537 ((mem_addr + length) >= (CYG_ADDRESS)ram_end)) {
1538 diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
1539 diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
1541 // Safety check - make sure the address range is not within the code we're running
1542 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr + length - 1))) {
1543 diag_printf("Can't program this region - contains code in use!\n");
1546 if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p",
1547 (void *)flash_addr, (void *)(flash_addr + length - 1),
1548 (void *)mem_addr)) {
1549 return; // The guy gave up
1553 // Erase area to be programmed
1554 if ((stat = flash_erase((void *)flash_addr, length, &err_addr)) != 0) {
1555 diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
1561 stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, &err_addr);
1563 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
1570 fis_erase(int argc, char *argv[])
1573 unsigned long length;
1574 CYG_ADDRESS flash_addr;
1575 bool flash_addr_set = false;
1576 bool length_set = false;
1578 struct option_info opts[2];
1580 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1581 &flash_addr, &flash_addr_set, "FLASH memory base address");
1582 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1583 &length, &length_set, "length");
1584 if (!scan_opts(argc, argv, 2, opts, 2, NULL, 0, NULL))
1586 fis_usage("invalid arguments");
1590 if (!flash_addr_set || !length_set) {
1591 fis_usage("missing argument");
1594 if (flash_addr_set &&
1595 ((stat = flash_verify_addr((void *)flash_addr)) ||
1596 (stat = flash_verify_addr((void *)(flash_addr + length - 1))))) {
1597 _show_invalid_flash_address(flash_addr, stat);
1600 if (flash_addr_set && flash_addr & (flash_block_size-1)) {
1601 diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
1602 diag_printf(" must be 0x%x aligned\n", flash_block_size);
1605 // Safety check - make sure the address range is not within the code we're running
1606 if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr + length - 1))) {
1607 diag_printf("Can't erase this region - contains code in use!\n");
1610 if ((stat = flash_erase((void *)flash_addr, length, &err_addr)) != 0) {
1611 diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
1615 #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
1618 fis_lock(int argc, char *argv[])
1622 unsigned long length;
1623 CYG_ADDRESS flash_addr;
1624 bool flash_addr_set = false;
1625 bool length_set = false;
1627 struct option_info opts[2];
1629 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1630 &flash_addr, &flash_addr_set, "FLASH memory base address");
1631 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1632 &length, &length_set, "length");
1633 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) {
1634 fis_usage("invalid arguments");
1637 #ifdef CYGOPT_REDBOOT_FIS
1638 /* Get parameters from image if specified */
1640 struct fis_image_desc *img;
1641 if ((img = fis_lookup(name, NULL)) == NULL) {
1642 diag_printf("No image '%s' found\n", name);
1646 flash_addr = img->flash_base;
1650 if (!flash_addr_set || !length_set) {
1651 fis_usage("missing argument");
1654 if (flash_addr_set &&
1655 ((stat = flash_verify_addr((void *)flash_addr)) ||
1656 (stat = flash_verify_addr((void *)(flash_addr + length - 1))))) {
1657 _show_invalid_flash_address(flash_addr, stat);
1660 if ((stat = flash_lock((void *)flash_addr, length, &err_addr)) != 0) {
1661 diag_printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
1666 fis_unlock(int argc, char *argv[])
1670 unsigned long length;
1671 CYG_ADDRESS flash_addr;
1672 bool flash_addr_set = false;
1673 bool length_set = false;
1675 struct option_info opts[2];
1677 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1678 &flash_addr, &flash_addr_set, "FLASH memory base address");
1679 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1680 &length, &length_set, "length");
1681 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) {
1682 fis_usage("invalid arguments");
1685 #ifdef CYGOPT_REDBOOT_FIS
1687 struct fis_image_desc *img;
1688 if ((img = fis_lookup(name, NULL)) == NULL) {
1689 diag_printf("No image '%s' found\n", name);
1693 flash_addr = img->flash_base;
1697 if (!flash_addr_set || !length_set) {
1698 fis_usage("missing argument");
1701 if (flash_addr_set &&
1702 ((stat = flash_verify_addr((void *)flash_addr)) ||
1703 (stat = flash_verify_addr((void *)(flash_addr + length - 1))))) {
1704 _show_invalid_flash_address(flash_addr, stat);
1708 if ((stat = flash_unlock((void *)flash_addr, length, &err_addr)) != 0) {
1709 diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
1714 // This is set non-zero if the FLASH subsystem has successfully been initialized
1715 int __flash_init = 0;
1720 if (!__flash_init) return;
1721 diag_printf("FLASH: %p - 0x%x, %d blocks of 0x%08x bytes each.\n",
1722 flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, flash_block_size);
1725 /* Returns -1 on failure, 0 on success, 1 if it was successfull
1726 but a failed fis update was detected */
1732 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
1733 struct fis_image_desc img0;
1734 struct fis_image_desc img1;
1735 int fis_update_was_interrupted = 0;
1738 //check the size of fis_valid_info
1739 CYG_ASSERT((sizeof(struct fis_valid_info) <= sizeof(img0.u.name)),
1740 "fis_valid_info size mismatch");
1741 //try to check the alignment of version_count
1742 CYG_ASSERT(((&img0.u.valid_info.version_count - &img0) % sizeof(unsigned long) == 0),
1743 "alignment problem");
1745 if (!__flash_init) {
1747 if ((stat = flash_init(diag_printf)) != 0) {
1748 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
1751 flash_get_limits(NULL, &flash_start, &flash_end);
1752 // Keep 'end' address as last valid location, to avoid wrap around problems
1753 flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
1754 flash_get_block_info(&flash_block_size, &flash_num_blocks);
1755 #ifdef CYGOPT_REDBOOT_FIS
1756 fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
1757 fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
1758 # if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
1759 fis_work_block = fis_zlib_common_buffer;
1760 if (CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
1761 diag_printf("FLASH: common buffer too small\n");
1765 workspace_end = (unsigned char *)(workspace_end - fisdir_size);
1766 fis_work_block = workspace_end;
1768 if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
1769 fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
1770 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK * flash_block_size));
1772 fis_addr = (void *)((CYG_ADDRESS)flash_start +
1773 (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK * flash_block_size));
1775 #if defined(CYGHWR_DEVS_FLASH_MXC_MULTI) && defined(MXCFLASH_SELECT_NAND)
1776 extern int mxc_nand_fis_start(void);
1777 if (IS_FIS_FROM_NAND()) {
1778 fis_addr = (void *)((CYG_ADDRESS)flash_start + mxc_nand_fis_start());
1782 #if defined(IMXFLASH_SELECT_SPI_NOR)
1783 extern int mxc_spi_nor_fis_start(void);
1784 if (IS_FIS_FROM_SPI_NOR()) {
1785 fis_addr = (void *)((CYG_ADDRESS)flash_start + mxc_spi_nor_fis_start());
1789 #if defined(MXCFLASH_SELECT_MMC)
1790 if (IS_FIS_FROM_MMC()) {
1791 fis_addr = (void *)REDBOOT_IMAGE_SIZE;
1795 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1796 diag_printf("FIS directory doesn't fit\n");
1799 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
1801 if (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK < 0) {
1802 redundant_fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
1803 (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK *
1806 redundant_fis_addr = (void *)((CYG_ADDRESS)flash_start +
1807 (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK *
1811 if (((CYG_ADDRESS)redundant_fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1812 diag_printf("Redundant FIS directory doesn't fit\n");
1815 FLASH_READ(fis_addr, &img0, sizeof(img0), &err_addr);
1816 FLASH_READ(redundant_fis_addr, &img1, sizeof(img1), &err_addr);
1818 if (strncmp(img0.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC,
1819 CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH) != 0) {
1820 memset(&img0, 0, sizeof(img0));
1823 if (strncmp(img1.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC,
1824 CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH) != 0) {
1825 memset(&img1, 0, sizeof(img0));
1828 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
1829 img0.u.valid_info.version_count = CYG_SWAP32(img0.u.valid_info.version_count);
1830 img1.u.valid_info.version_count = CYG_SWAP32(img1.u.valid_info.version_count);
1833 if (fis_get_valid_buf(&img0, &img1, &fis_update_was_interrupted) == 1) {
1834 // Valid, so swap primary and secondary
1837 fis_addr = redundant_fis_addr;
1838 redundant_fis_addr = tmp;
1841 fis_read_directory();
1844 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
1845 if (fis_update_was_interrupted)
1854 // Wrapper to avoid compiler warnings
1856 _do_flash_init(void)
1858 static int init_done = 0;
1859 if (init_done) return;
1864 RedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);
1867 do_fis(int argc, char *argv[])
1872 fis_usage("too few arguments");
1875 if (do_flash_init() < 0) {
1876 diag_printf("Sorry, no FLASH memory is available\n");
1879 if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__,
1880 argv[1])) != NULL) {
1881 (cmd->fun)(argc, argv);
1884 fis_usage("unrecognized command");