void do_dump(int argc, char *argv[]) { struct option_info opts[6]; unsigned long base, len; bool base_set, len_set; static unsigned long _base, _len; static char _size = 1; bool srec_dump, set_32bit, set_16bit, set_8bit; int i, n, off, cksum; cyg_uint8 ch; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void *)&base, (bool *)&base_set, "base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&len, (bool *)&len_set, "length"); init_opts(&opts[2], 's', false, OPTION_ARG_TYPE_FLG, (void *)&srec_dump, 0, "dump data using Morotola S-records"); init_opts(&opts[3], '4', false, OPTION_ARG_TYPE_FLG, (void *)&set_32bit, (bool *)0, "dump 32 bit units"); init_opts(&opts[4], '2', false, OPTION_ARG_TYPE_FLG, (void *)&set_16bit, (bool *)0, "dump 16 bit units"); init_opts(&opts[5], '1', false, OPTION_ARG_TYPE_FLG, (void *)&set_8bit, (bool *)0, "dump 8 bit units"); if (!scan_opts(argc, argv, 1, opts, 6, 0, 0, "")) { return; } if (!base_set) { if (_base == 0) { diag_printf("Dump what [location]?\n"); return; } base = _base; if (!len_set) { len = _len; len_set = true; } } if (set_32bit) { _size = 4; } else if (set_16bit) { _size = 2; } else if (set_8bit) { _size = 1; } if (!len_set) { len = 32; } if (srec_dump) { off = 0; while (off < len) { n = (len > 16) ? 16 : len; cksum = n+5; diag_printf("S3%02X%08lX", n+5, off+base); for (i = 0; i < 4; i++) { cksum += (((base+off)>>(i*8)) & 0xFF); } for (i = 0; i < n; i++) { ch = *(cyg_uint8 *)(base+off+i); diag_printf("%02X", ch); cksum += ch; } diag_printf("%02X\n", ~cksum & 0xFF); off += n; } } else { switch( _size ) {
static void fis_create(int argc, char *argv[]) { int i, stat; unsigned long length, img_size; CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr; char *name; bool mem_addr_set = false; bool exec_addr_set = false; bool entry_addr_set = false; bool flash_addr_set = false; bool length_set = false; bool img_size_set = false; bool no_copy = false; void *err_addr; struct fis_image_desc *img = NULL; bool defaults_assumed; struct option_info opts[7]; bool prog_ok = true; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM, (void *)&exec_addr, (bool *)&exec_addr_set, "ram base address"); init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM, (void *)&entry_addr, (bool *)&entry_addr_set, "entry point address"); init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM, (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "image length [in FLASH]"); init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM, (void *)&img_size, (bool *)&img_size_set, "image size [actual data]"); init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG, (void *)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory"); if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name")) { fis_usage("invalid arguments"); return; } fis_read_directory(); defaults_assumed = false; if (name) { // Search existing files to acquire defaults for params not specified: img = fis_lookup(name, NULL); if (img) { // Found it, so get image size from there if (!length_set) { length_set = true; length = img->size; defaults_assumed = true; } } } if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) && (load_address_end) < (CYG_ADDRESS)ram_end) { mem_addr = load_address; mem_addr_set = true; defaults_assumed = true; // Get entry address from loader, unless overridden if (!entry_addr_set) entry_addr = entry_address; if (!length_set) { length = load_address_end - load_address; length_set = true; } else if (defaults_assumed && !img_size_set) { /* We got length from the FIS table, so the size of the actual loaded image becomes img_size */ img_size = load_address_end - load_address; img_size_set = true; } } // Get the remaining fall-back values from the fis if (img) { if (!exec_addr_set) { // Preserve "normal" behaviour exec_addr_set = true; exec_addr = flash_addr_set ? flash_addr : mem_addr; } if (!flash_addr_set) { flash_addr_set = true; flash_addr = img->flash_base; defaults_assumed = true; } } if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) || !length_set || !name) { fis_usage("required parameter missing"); return; } if (!img_size_set) { img_size = length; } // 'length' is size of FLASH image, 'img_size' is actual data size // Round up length to FLASH block size #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size; if (length < img_size) { diag_printf("Invalid FLASH image size/length combination\n"); return; } #endif if (flash_addr_set && ((stat = flash_verify_addr((void *)flash_addr)) || (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { _show_invalid_flash_address(flash_addr, stat); return; } if (flash_addr_set && ((flash_addr & (flash_block_size-1)) != 0)) { diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); diag_printf(" must be 0x%x aligned\n", flash_block_size); return; } if (strlen(name) >= sizeof(img->name)) { diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name)); return; } if (!no_copy) { if ((mem_addr < (CYG_ADDRESS)ram_start) || ((mem_addr+img_size) >= (CYG_ADDRESS)ram_end)) { diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); } if (!flash_addr_set && !fis_find_free(&flash_addr, length)) { diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length); return; } } // First, see if the image by this name has agreable properties if (img) { if (flash_addr_set && (img->flash_base != flash_addr)) { diag_printf("Image found, but flash address (%p)\n" " is incorrect (present image location %p)\n", flash_addr, img->flash_base); return; } if (img->size != length) { diag_printf("Image found, but length (0x%lx, necessitating image size 0x%lx)\n" " is incorrect (present image size 0x%lx)\n", img_size, length, img->size); return; } if (!verify_action("An image named '%s' exists", name)) { return; } else { if (defaults_assumed) { if (no_copy && !verify_action("* CAUTION * about to program '%s'\n at %p..%p from %p", name, (void *)flash_addr, (void *)(flash_addr+img_size-1), (void *)mem_addr)) { return; // The guy gave up } } } } else { #ifdef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS // Make sure that any FLASH address specified directly is truly free if (flash_addr_set && !no_copy) { struct free_chunk chunks[CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS]; int idx, num_chunks; bool is_free = false; num_chunks = find_free(chunks); for (idx = 0; idx < num_chunks; idx++) { if ((flash_addr >= chunks[idx].start) && ((flash_addr+length-1) <= chunks[idx].end)) { is_free = true; } } if (!is_free) { diag_printf("Invalid FLASH address - not free!\n"); return; } } #endif // If not image by that name, try and find an empty slot img = (struct fis_image_desc *)fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { if (img->name[0] == (unsigned char)0xFF) { break; } } } if (!no_copy) { // Safety check - make sure the address range is not within the code we're running if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+img_size-1))) { diag_printf("Can't program this region - contains code in use!\n"); return; } if (prog_ok) { // Erase area to be programmed if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) { diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat)); prog_ok = false; } } if (prog_ok) { // Now program it if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); prog_ok = false; } } } if (prog_ok) { // Update directory memset(img, 0, sizeof(*img)); strcpy(img->name, name); img->flash_base = flash_addr; img->mem_base = exec_addr_set ? exec_addr : (flash_addr_set ? flash_addr : mem_addr); img->entry_point = entry_addr_set ? entry_addr : (CYG_ADDRESS)entry_address; // Hope it's been set img->size = length; img->data_length = img_size; #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK if (!no_copy) { img->file_cksum = cyg_crc32((unsigned char *)mem_addr, img_size); } else { // No way to compute this, sorry img->file_cksum = 0; } #endif fis_update_directory(); } }
// // Execute a Linux kernel - this is a RedBoot CLI command // static void do_exec(int argc, char *argv[]) { unsigned long entry; bool wait_time_set, cmd_line_set; int wait_time; char *cmd_line; char *cline; struct option_info opts[2]; hal_virtual_comm_table_t *__chan; int baud_rate; bd_t *board_info; CYG_INTERRUPT_STATE oldints; unsigned long sp = CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE; init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, (void *)&wait_time, (bool *)&wait_time_set, "wait timeout"); init_opts(&opts[1], 'c', true, OPTION_ARG_TYPE_STR, (void *)&cmd_line, (bool *)&cmd_line_set, "kernel command line"); entry = entry_address; // Default from last 'load' operation if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, "[physical] starting address")) { return; } if (entry == (unsigned long)NO_MEMORY) { diag_printf("Can't execute Linux - invalid entry address\n"); return; } // Determine baud rate on current console __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); baud_rate = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_GETBAUD); if (baud_rate <= 0) { baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD; } // Make a little space at the top of the stack, and align to // 64-bit boundary. sp = (sp-128) & ~7; // The Linux boot code uses this space for FIFOs // Copy the commandline onto the stack, and set the SP to just below it. if (cmd_line_set) { int len,i; // get length of string for( len = 0; cmd_line[len] != '\0'; len++ ); // decrement sp by length of string and align to // word boundary. sp = (sp-(len+1)) & ~3; // assign this SP value to command line start cline = (char *)sp; // copy command line over. for( i = 0; i < len; i++ ) cline[i] = cmd_line[i]; cline[len] = '\0'; } else { cline = (char *)NULL; } // Set up parameter struct at top of stack sp = sp-sizeof(bd_t); board_info = (bd_t *)sp; memset(board_info, sizeof(*board_info), 0); board_info->bi_tag = 0x42444944; board_info->bi_size = sizeof(*board_info); board_info->bi_revision = 1; board_info->bi_bdate = 0x06012002; board_info->bi_memstart = CYGMEM_REGION_ram; board_info->bi_memsize = CYGMEM_REGION_ram_SIZE; board_info->bi_baudrate = baud_rate; board_info->bi_cmdline = cline; #ifdef CYGPKG_REDBOOT_NETWORKING memcpy(board_info->bi_enetaddr, __local_enet_addr, sizeof(enet_addr_t)); #endif // Call platform specific code to fill in the platform/architecture specific details plf_redboot_linux_exec(board_info); // adjust SP to 64 byte boundary, and leave a little space // between it and the commandline for PowerPC calling // conventions. sp = (sp-64)&~63; if (wait_time_set) { int script_timeout_ms = wait_time * 1000; #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT unsigned char *hold_script = script; script = (unsigned char *)0; #endif diag_printf("About to start execution at %p - abort with ^C within %d seconds\n", (void *)entry, wait_time); while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) { int res; char line[80]; res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT); if (res == _GETS_CTRLC) { #ifdef CYGFUN_REDBOOT_BOOT_SCRIPT script = hold_script; // Re-enable script #endif return; } script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT; } } #ifdef CYGPKG_IO_ETH_DRIVERS eth_drv_stop(); #endif // Disable interrupts HAL_DISABLE_INTERRUPTS(oldints); // Put the caches to sleep. HAL_DCACHE_SYNC(); HAL_ICACHE_DISABLE(); HAL_DCACHE_DISABLE(); HAL_DCACHE_SYNC(); HAL_ICACHE_INVALIDATE_ALL(); HAL_DCACHE_INVALIDATE_ALL(); // diag_printf("entry %08x, sp %08x, info %08x, cmd line %08x, baud %d\n", // entry, sp, board_info, cline, baud_rate); // breakpoint(); // Call into Linux __asm__ volatile ( // Start by disabling MMU - the mappings are // 1-1 so this should not cause any problems "mfmsr 3\n" "li 4,0xFFFFFFCF\n" "and 3,3,4\n" "sync\n" "mtmsr 3\n" "sync\n" // Now set up parameters to jump into linux "mtlr %0\n" // set entry address in LR "mr 1,%1\n" // set stack pointer "mr 3,%2\n" // set board info in R3 "mr 4,%3\n" // set command line in R4 "blr \n" // jump into linux : : "r"(entry),"r"(sp),"r"(board_info),"r"(cline) : "r3", "r4" ); }
static void do_flash_config(int argc, char *argv[]) { bool need_update = false; struct config_option *optend = __CONFIG_options_TAB_END__; struct config_option *opt = __CONFIG_options_TAB__; struct option_info opts[5]; bool list_only; bool nicknames; bool fullnames; bool dumbterminal; int list_opt = 0; unsigned char *dp; int len, ret; char *title; char *onlyone = NULL; char *onevalue = NULL; bool doneone = false; bool init = false; #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH if (!__flash_init) { diag_printf("Sorry, no FLASH memory is available\n"); return; } #endif memcpy(backup_config, config, sizeof(struct _config)); script = (unsigned char *)0; init_opts(&opts[0], 'l', false, OPTION_ARG_TYPE_FLG, (void *)&list_only, (bool *)0, "list configuration only"); init_opts(&opts[1], 'n', false, OPTION_ARG_TYPE_FLG, (void *)&nicknames, (bool *)0, "show nicknames"); init_opts(&opts[2], 'f', false, OPTION_ARG_TYPE_FLG, (void *)&fullnames, (bool *)0, "show full names"); init_opts(&opts[3], 'i', false, OPTION_ARG_TYPE_FLG, (void *)&init, (bool *)0, "initialize configuration database"); init_opts(&opts[4], 'd', false, OPTION_ARG_TYPE_FLG, (void *)&dumbterminal, (bool *)0, "dumb terminal: no clever edits"); // First look to see if we are setting or getting a single option // by just quoting its nickname if ( (2 == argc && '-' != argv[1][0]) || (3 == argc && '-' != argv[1][0] && '-' != argv[2][0])) { // then the command was "fconfig foo [value]" onlyone = argv[1]; onevalue = (3 == argc) ? argv[2] : NULL; list_opt = LIST_OPT_NICKNAMES; } // Next see if we are setting or getting a single option with a dumb // terminal invoked, ie. no line editing. else if (3 == argc && '-' == argv[1][0] && 'd' == argv[1][1] && 0 == argv[1][2] && '-' != argv[2][0]) { // then the command was "fconfig -d foo" onlyone = argv[2]; onevalue = NULL; list_opt = LIST_OPT_NICKNAMES | LIST_OPT_DUMBTERM; } else { if (!scan_opts(argc, argv, 1, opts, 5, 0, 0, "")) return; list_opt |= list_only ? LIST_OPT_LIST_ONLY : 0; list_opt |= nicknames ? LIST_OPT_NICKNAMES : LIST_OPT_FULLNAMES; list_opt |= fullnames ? LIST_OPT_FULLNAMES : 0; list_opt |= dumbterminal ? LIST_OPT_DUMBTERM : 0; } if (init && verify_action("Initialize non-volatile configuration")) { config_init(); need_update = true; } dp = &config->config_data[0]; while (dp < &config->config_data[sizeof(config->config_data)]) { if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) { break; } len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) + config_length(CONFIG_OBJECT_TYPE(dp)); // Provide a title for well known [i.e. builtin] objects title = (char *)NULL; opt = __CONFIG_options_TAB__; while (opt != optend) { if (strcmp(opt->key, CONFIG_OBJECT_KEY(dp)) == 0) { title = opt->title; break; } opt++; } if ( onlyone && 0 != strcmp(CONFIG_OBJECT_KEY(dp), onlyone) ) ret = CONFIG_OK; // skip this entry else { doneone = true; ret = get_config(dp, title, list_opt, onevalue); // do this opt } switch (ret) { case CONFIG_DONE: goto done; case CONFIG_ABORT: memcpy(config, backup_config, sizeof(struct _config)); return; case CONFIG_CHANGED: need_update = true; case CONFIG_OK: dp += len; break; case CONFIG_BACK: dp = &config->config_data[0]; continue; case CONFIG_BAD: // Nothing - make him do it again diag_printf ("** invalid entry\n"); onevalue = NULL; // request a good value be typed in - or abort/whatever } } done: if (NULL != onlyone && !doneone) { #ifdef CYGSEM_REDBOOT_ALLOW_DYNAMIC_FLASH_CONFIG_DATA if (verify_action("** entry '%s' not found - add", onlyone)) { struct config_option opt; diag_printf("Trying to add value\n"); } #else diag_printf("** entry '%s' not found\n", onlyone); #endif } if (!need_update) return; flash_write_config(true); }
void do_pcidump(int argc, char *argv[]) { struct option_info opts[4]; unsigned long bus; unsigned long device; unsigned long function; unsigned long length; unsigned int value; static unsigned int _bus = 0xFFFFFFFF; static unsigned int _offset = 0xFFFFFFFF; static unsigned int _function = 0xFFFFFFFF; static unsigned int _device = 0xFFFFFFFF; static unsigned int _length = 0xFFFFFFFF; bool bus_set; bool device_set; bool function_set; bool length_set; cyg_uint8 devfn; int i; int j; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void **)&bus, (bool *)&bus_set, "bus"); init_opts(&opts[1], 'd', true, OPTION_ARG_TYPE_NUM, (void **)&device, (bool *)&device_set, "device"); init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_NUM, (void **)&function, (bool *)&function_set, "function"); init_opts(&opts[3], 'l', true, OPTION_ARG_TYPE_NUM, (void **)&length, (bool *)&length_set, "length"); if (!scan_opts(argc, argv, 1, opts, 4, 0, 0, "")) { return; } if (!bus_set) { if (_bus == 0xFFFFFFFF) { diag_printf("Pdump what [bus]?\n"); return; } } else if (!device_set) { if (_device == 0xFFFFFFFF) { diag_printf("Pdump what [device]?\n"); return; } } else { _offset = 0; _device = device; _bus = bus; } if (_device > 32) { diag_printf("Invalid Device Number - %d\n", _device); return; } if (!function_set) { if (_function == 0xFFFFFFFF) _function = 0; } else _function = function; if (_function > 7) { diag_printf("Invalid Function Number - %d\n", _function); return; } if (!length_set) { if (_length == 0xFFFFFFFF) _length = 16; } else _length = length; #if 0 /* If device number is on the secondary bus, set bus number to 1 */ if (_device >= P4205_SERIAL_MEZZ_CFG_ADDR) bus = 1; #endif devfn = CYG_PCI_DEV_MAKE_DEVFN(_device, _function); for (i = 0; i < _length; i += 4) { diag_printf("%08x: ", _offset); for (j = 0; j < 4; ++j, _offset+=4) { cyg_pcihw_read_config_uint32(_bus, devfn, _offset, &value); diag_printf("%08x ", value); } diag_printf("\n"); } }
// Mount disk/filesystem static void do_mount(int argc, char *argv[]) { char *dev_str = "<undefined>", *type_str, *mp_str; bool dev_set = false, type_set = false; struct option_info opts[3]; int err, num_opts = 2; int i,m=0; /* Set to 0 to silence warning */ #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY char *part_str; bool part_set = false; #endif init_opts(&opts[0], 'd', true, OPTION_ARG_TYPE_STR, (void *)&dev_str, &dev_set, "device"); init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_STR, (void *)&type_str, &type_set, "fstype"); #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_STR, (void *)&part_str, &part_set, "partition"); num_opts++; #endif CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 1, opts, num_opts, &mp_str, OPTION_ARG_TYPE_STR, "mountpoint")) return; if (!type_set) { err_printf("fs mount: Must specify file system type\n"); return; } if( mp_str == 0 ) mp_str = "/"; if( mount_count >= MAX_MOUNTS ) { err_printf("fs mount: Maximum number of mounts exceeded\n"); return; } #ifdef CYGPKG_IO_FLASH_BLOCK_DEVICE_LEGACY if (part_set) { int len; cyg_io_handle_t h; if (dev_set && strcmp(dev_str, CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1)) { err_printf("fs mount: May only set one of <device> or <partition>\n"); return; } dev_str = CYGDAT_IO_FLASH_BLOCK_DEVICE_NAME_1; len = strlen(part_str); err = cyg_io_lookup(dev_str, &h); if (err < 0) { err_printf("fs mount: cyg_io_lookup of \"%s\" returned %d\n", err); return; } err = cyg_io_set_config(h, CYG_IO_SET_CONFIG_FLASH_FIS_NAME, part_str, &len); if (err < 0) { diag_printf("fs mount: FIS partition \"%s\" not found\n", part_str); return; } } #endif for( i = 0; i < MAX_MOUNTS; i++ ) { if( mounts[i].mp_str[0] != '\0' ) { if( strcmp(mounts[i].dev_str, dev_str ) == 0 ) { err_printf("fs mount: Device %s already mounted\n",dev_str); return; } } else m = i; } strcpy( mounts[m].mp_str, mp_str ); strcpy( mounts[m].dev_str, dev_str ); strcpy( mounts[m].type_str, type_str ); err = mount(mounts[m].dev_str, mounts[m].mp_str, mounts[m].type_str); if (err) { err_printf("fs mount: mount(%s,%s,%s) failed %d\n", dev_str, mp_str, type_str, errno); mounts[m].mp_str[0] = '\0'; // mount failed so don't let it appear mounted } else { if( mount_count == 0 ) chdir( "/" ); mount_count++; } }
static void do_try_reset(int argc, char *argv[]) { struct option_info opts[4]; bool flag_1 = false; bool flag_2 = false; bool flag_3 = false; bool flag_4 = false; cyg_uint16 tmp = 0; init_opts(&opts[0], '1', false, OPTION_ARG_TYPE_FLG, (void**)&flag_1, 0, "only try phase 1"); init_opts(&opts[1], '2', false, OPTION_ARG_TYPE_FLG, (void**)&flag_2, 0, "try phase 1 & phase 2"); init_opts(&opts[2], '3', false, OPTION_ARG_TYPE_FLG, (void**)&flag_3, 0, "try phase 1 through phase 3"); init_opts(&opts[3], '4', false, OPTION_ARG_TYPE_FLG, (void**)&flag_4, 0, "try phase 1 through phase 4"); if (!scan_opts(argc, argv, 1, opts, sizeof(opts) / sizeof(opts[0]), 0, 0, 0)) { return; } diag_printf("flag_4 = %d, flag_3 = %d, flag_2 = %d, flag_1 = %d\n", flag_4, flag_3, flag_2, flag_1); if (flag_4) { flag_3 = flag_2 = flag_1 = true; } else if (flag_3) { flag_2 = flag_1 = true; } else if (flag_2) { flag_1 = true; } diag_printf("flag_4 = %d, flag_3 = %d, flag_2 = %d, flag_1 = %d\n", flag_4, flag_3, flag_2, flag_1); if (flag_1) { HAL_READ_UINT16(CLKM_ARM_IDLECT2, tmp); diag_printf("tmp = %04X\n", tmp); } if (flag_2) { tmp |= 1; diag_printf("Writing %04X to %08X\n", tmp, CLKM_ARM_IDLECT2); HAL_WRITE_UINT16(CLKM_ARM_IDLECT2, tmp | 1); } if (flag_3) { diag_printf("Writing %04X to %08X\n", 0x80F5, WATCHDOG_TIMER_MODE); HAL_WRITE_UINT16(WATCHDOG_TIMER_MODE, 0x80F5); \ } if (flag_4) { diag_printf("Writing %04X to %08X\n", 0x80F5, WATCHDOG_TIMER_MODE); HAL_WRITE_UINT16(WATCHDOG_TIMER_MODE, 0x80F5); \ } diag_printf("try_reset: done\n"); }
void do_mcmp(int argc, char *argv[]) { // Fill a region of memory with a pattern struct option_info opts[6]; unsigned long src_base, dst_base; long len; bool src_base_set, dst_base_set, len_set; bool set_32bit, set_16bit, set_8bit; init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM, (void **)&src_base, (bool *)&src_base_set, "base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void **)&len, (bool *)&len_set, "length"); init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_NUM, (void **)&dst_base, (bool *)&dst_base_set, "base address"); init_opts(&opts[3], '4', false, OPTION_ARG_TYPE_FLG, (void *)&set_32bit, (bool *)0, "fill 32 bit units"); init_opts(&opts[4], '2', false, OPTION_ARG_TYPE_FLG, (void **)&set_16bit, (bool *)0, "fill 16 bit units"); init_opts(&opts[5], '1', false, OPTION_ARG_TYPE_FLG, (void **)&set_8bit, (bool *)0, "fill 8 bit units"); if (!scan_opts(argc, argv, 1, opts, 6, 0, 0, "")) { return; } if (!src_base_set || !dst_base_set || !len_set) { diag_printf("usage: mcmp -s <addr> -d <addr> -l <length> [-1|-2|-4]\n"); return; } // No checks here if (set_8bit) { // Compare 8 bits at a time while ((len -= sizeof(cyg_uint8)) >= 0) { if (*((cyg_uint8 *)src_base)++ != *((cyg_uint8 *)dst_base)++) { ((cyg_uint8 *)src_base)--; ((cyg_uint8 *)dst_base)--; diag_printf("Buffers don't match - %p=0x%02x, %p=0x%02x\n", src_base, *((cyg_uint8 *)src_base), dst_base, *((cyg_uint8 *)dst_base)); return; } } } else if (set_16bit) { // Compare 16 bits at a time while ((len -= sizeof(cyg_uint16)) >= 0) { if (*((cyg_uint16 *)src_base)++ != *((cyg_uint16 *)dst_base)++) { ((cyg_uint16 *)src_base)--; ((cyg_uint16 *)dst_base)--; diag_printf("Buffers don't match - %p=0x%04x, %p=0x%04x\n", src_base, *((cyg_uint16 *)src_base), dst_base, *((cyg_uint16 *)dst_base)); return; } } } else { // Default - 32 bits while ((len -= sizeof(cyg_uint32)) >= 0) { if (*((cyg_uint32 *)src_base)++ != *((cyg_uint32 *)dst_base)++) { ((cyg_uint32 *)src_base)--; ((cyg_uint32 *)dst_base)--; diag_printf("Buffers don't match - %p=0x%08x, %p=0x%08x\n", src_base, *((cyg_uint32 *)src_base), dst_base, *((cyg_uint32 *)dst_base)); return; } } } }
int main(int argc, char *argv[], char *envp[]) { pid_t pid = 0, tree_id = 0; int ret = -1; bool usage_error = true; bool has_exec_cmd = false; int opt, idx; int log_level = LOG_UNSET; char *imgs_dir = "."; char *work_dir = NULL; static const char short_opts[] = "dSsRf:F:t:p:hcD:o:n:v::x::Vr:jlW:L:M:"; static struct option long_opts[] = { { "tree", required_argument, 0, 't' }, { "pid", required_argument, 0, 'p' }, { "leave-stopped", no_argument, 0, 's' }, { "leave-running", no_argument, 0, 'R' }, { "restore-detached", no_argument, 0, 'd' }, { "restore-sibling", no_argument, 0, 'S' }, { "daemon", no_argument, 0, 'd' }, { "contents", no_argument, 0, 'c' }, { "file", required_argument, 0, 'f' }, { "fields", required_argument, 0, 'F' }, { "images-dir", required_argument, 0, 'D' }, { "work-dir", required_argument, 0, 'W' }, { "log-file", required_argument, 0, 'o' }, { "namespaces", required_argument, 0, 'n' }, { "root", required_argument, 0, 'r' }, { USK_EXT_PARAM, optional_argument, 0, 'x' }, { "help", no_argument, 0, 'h' }, { SK_EST_PARAM, no_argument, 0, 1042 }, { "close", required_argument, 0, 1043 }, { "log-pid", no_argument, 0, 1044 }, { "version", no_argument, 0, 'V' }, { "evasive-devices", no_argument, 0, 1045 }, { "pidfile", required_argument, 0, 1046 }, { "veth-pair", required_argument, 0, 1047 }, { "action-script", required_argument, 0, 1049 }, { LREMAP_PARAM, no_argument, 0, 1041 }, { OPT_SHELL_JOB, no_argument, 0, 'j' }, { OPT_FILE_LOCKS, no_argument, 0, 'l' }, { "page-server", no_argument, 0, 1050 }, { "address", required_argument, 0, 1051 }, { "port", required_argument, 0, 1052 }, { "prev-images-dir", required_argument, 0, 1053 }, { "ms", no_argument, 0, 1054 }, { "track-mem", no_argument, 0, 1055 }, { "auto-dedup", no_argument, 0, 1056 }, { "libdir", required_argument, 0, 'L' }, { "cpu-cap", optional_argument, 0, 1057 }, { "force-irmap", no_argument, 0, 1058 }, { "ext-mount-map", required_argument, 0, 'M' }, { "exec-cmd", no_argument, 0, 1059 }, { "manage-cgroups", optional_argument, 0, 1060 }, { "cgroup-root", required_argument, 0, 1061 }, { "inherit-fd", required_argument, 0, 1062 }, { "feature", required_argument, 0, 1063 }, { "skip-mnt", required_argument, 0, 1064 }, { "enable-fs", required_argument, 0, 1065 }, { "enable-external-sharing", no_argument, 0, 1066 }, { "enable-external-masters", no_argument, 0, 1067 }, { "freeze-cgroup", required_argument, 0, 1068 }, { "ghost-limit", required_argument, 0, 1069 }, { "irmap-scan-path", required_argument, 0, 1070 }, { }, }; BUILD_BUG_ON(PAGE_SIZE != PAGE_IMAGE_SIZE); if (fault_injection_init()) return 1; cr_pb_init(); if (restrict_uid(getuid(), getgid())) return 1; setproctitle_init(argc, argv, envp); if (argc < 2) goto usage; init_opts(); if (init_service_fd()) return 1; if (!strcmp(argv[1], "swrk")) { if (argc < 3) goto usage; /* * This is to start criu service worker from libcriu calls. * The usage is "criu swrk <fd>" and is not for CLI/scripts. * The arguments semantics can change at any tyme with the * corresponding lib call change. */ opts.swrk_restore = true; return cr_service_work(atoi(argv[2])); } while (1) { idx = -1; opt = getopt_long(argc, argv, short_opts, long_opts, &idx); if (opt == -1) break; switch (opt) { case 's': opts.final_state = TASK_STOPPED; break; case 'R': opts.final_state = TASK_ALIVE; break; case 'x': if (optarg && unix_sk_ids_parse(optarg) < 0) return 1; opts.ext_unix_sk = true; break; case 'p': pid = atoi(optarg); if (pid <= 0) goto bad_arg; break; case 't': tree_id = atoi(optarg); if (tree_id <= 0) goto bad_arg; break; case 'c': opts.show_pages_content = true; break; case 'f': opts.show_dump_file = optarg; break; case 'F': opts.show_fmt = optarg; break; case 'r': opts.root = optarg; break; case 'd': opts.restore_detach = true; break; case 'S': opts.restore_sibling = true; break; case 'D': imgs_dir = optarg; break; case 'W': work_dir = optarg; break; case 'o': opts.output = optarg; break; case 'n': if (parse_ns_string(optarg)) goto bad_arg; break; case 'v': if (log_level == LOG_UNSET) log_level = 0; if (optarg) { if (optarg[0] == 'v') /* handle -vvvvv */ log_level += strlen(optarg) + 1; else log_level = atoi(optarg); } else log_level++; break; case 1041: pr_info("Will allow link remaps on FS\n"); opts.link_remap_ok = true; break; case 1042: pr_info("Will dump TCP connections\n"); opts.tcp_established_ok = true; break; case 1043: { int fd; fd = atoi(optarg); pr_info("Closing fd %d\n", fd); close(fd); break; } case 1044: opts.log_file_per_pid = 1; break; case 1045: opts.evasive_devices = true; break; case 1046: opts.pidfile = optarg; break; case 1047: { char *aux; aux = strchr(optarg, '='); if (aux == NULL) goto bad_arg; *aux = '\0'; if (veth_pair_add(optarg, aux + 1)) return 1; } break; case 1049: if (add_script(optarg, 0)) return 1; break; case 1050: opts.use_page_server = true; break; case 1051: opts.addr = optarg; break; case 1052: opts.ps_port = htons(atoi(optarg)); if (!opts.ps_port) goto bad_arg; break; case 'j': opts.shell_job = true; break; case 'l': opts.handle_file_locks = true; break; case 1053: opts.img_parent = optarg; break; case 1055: opts.track_mem = true; break; case 1056: opts.auto_dedup = true; break; case 1057: if (parse_cpu_cap(&opts, optarg)) goto usage; break; case 1058: opts.force_irmap = true; break; case 1054: opts.check_ms_kernel = true; break; case 'L': opts.libdir = optarg; break; case 1059: has_exec_cmd = true; break; case 1060: if (parse_manage_cgroups(&opts, optarg)) goto usage; break; case 1061: { char *path, *ctl; path = strchr(optarg, ':'); if (path) { *path = '\0'; path++; ctl = optarg; } else { path = optarg; ctl = NULL; } if (new_cg_root_add(ctl, path)) return -1; } break; case 1062: if (inherit_fd_parse(optarg) < 0) return 1; break; case 1063: if (check_add_feature(optarg) < 0) return 1; break; case 1064: if (!add_skip_mount(optarg)) return 1; break; case 1065: if (!add_fsname_auto(optarg)) return 1; break; case 1066: opts.enable_external_sharing = true; break; case 1067: opts.enable_external_masters = true; break; case 1068: opts.freeze_cgroup = optarg; break; case 1069: opts.ghost_limit = parse_size(optarg); break; case 1070: if (irmap_scan_path_add(optarg)) return -1; break; case 'M': { char *aux; if (strcmp(optarg, "auto") == 0) { opts.autodetect_ext_mounts = true; break; } aux = strchr(optarg, ':'); if (aux == NULL) goto bad_arg; *aux = '\0'; if (ext_mount_add(optarg, aux + 1)) return 1; } break; case 'V': pr_msg("Version: %s\n", CRIU_VERSION); if (strcmp(CRIU_GITID, "0")) pr_msg("GitID: %s\n", CRIU_GITID); return 0; case 'h': usage_error = false; goto usage; default: goto usage; } } if (!opts.restore_detach && opts.restore_sibling) { pr_msg("--restore-sibling only makes sense with --restore-detach\n"); return 1; } if (!opts.autodetect_ext_mounts && (opts.enable_external_masters || opts.enable_external_sharing)) { pr_msg("must specify --ext-mount-map auto with --enable-external-{sharing|masters}"); return 1; } if (work_dir == NULL) work_dir = imgs_dir; if (optind >= argc) { pr_msg("Error: command is required\n"); goto usage; } if (has_exec_cmd) { if (argc - optind <= 1) { pr_msg("Error: --exec-cmd requires a command\n"); goto usage; } if (strcmp(argv[optind], "restore")) { pr_msg("Error: --exec-cmd is available for the restore command only\n"); goto usage; } if (opts.restore_detach) { pr_msg("Error: --restore-detached and --exec-cmd cannot be used together\n"); goto usage; } opts.exec_cmd = xmalloc((argc - optind) * sizeof(char *)); if (!opts.exec_cmd) return 1; memcpy(opts.exec_cmd, &argv[optind + 1], (argc - optind - 1) * sizeof(char *)); opts.exec_cmd[argc - optind - 1] = NULL; } /* We must not open imgs dir, if service is called */ if (strcmp(argv[optind], "service")) { ret = open_image_dir(imgs_dir); if (ret < 0) return 1; } if (chdir(work_dir)) { pr_perror("Can't change directory to %s", work_dir); return 1; } log_set_loglevel(log_level); if (log_init(opts.output)) return 1; if (!list_empty(&opts.inherit_fds)) { if (strcmp(argv[optind], "restore")) { pr_err("--inherit-fd is restore-only option\n"); return 1; } /* now that log file is set up, print inherit fd list */ inherit_fd_log(); } if (opts.img_parent) pr_info("Will do snapshot from %s\n", opts.img_parent); if (!strcmp(argv[optind], "dump")) { preload_socket_modules(); if (!tree_id) goto opt_pid_missing; return cr_dump_tasks(tree_id); } if (!strcmp(argv[optind], "pre-dump")) { if (!tree_id) goto opt_pid_missing; return cr_pre_dump_tasks(tree_id) != 0; } if (!strcmp(argv[optind], "restore")) { if (tree_id) pr_warn("Using -t with criu restore is obsoleted\n"); ret = cr_restore_tasks(); if (ret == 0 && opts.exec_cmd) { close_pid_proc(); execvp(opts.exec_cmd[0], opts.exec_cmd); pr_perror("Failed to exec command %s", opts.exec_cmd[0]); ret = 1; } return ret != 0; } if (!strcmp(argv[optind], "show")) return cr_show(pid) != 0; if (!strcmp(argv[optind], "check")) return cr_check() != 0; if (!strcmp(argv[optind], "exec")) { if (!pid) pid = tree_id; /* old usage */ if (!pid) goto opt_pid_missing; return cr_exec(pid, argv + optind + 1) != 0; } if (!strcmp(argv[optind], "page-server")) return cr_page_server(opts.daemon_mode, -1) > 0 ? 0 : 1; if (!strcmp(argv[optind], "service")) return cr_service(opts.daemon_mode); if (!strcmp(argv[optind], "dedup")) return cr_dedup() != 0; if (!strcmp(argv[optind], "cpuinfo")) { if (!argv[optind + 1]) goto usage; if (!strcmp(argv[optind + 1], "dump")) return cpuinfo_dump(); else if (!strcmp(argv[optind + 1], "check")) return cpuinfo_check(); } pr_msg("Error: unknown command: %s\n", argv[optind]); usage: pr_msg("\n" "Usage:\n" " criu dump|pre-dump -t PID [<options>]\n" " criu restore [<options>]\n" " criu check [--ms]\n" " criu exec -p PID <syscall-string>\n" " criu page-server\n" " criu service [<options>]\n" " criu dedup\n" "\n" "Commands:\n" " dump checkpoint a process/tree identified by pid\n" " pre-dump pre-dump task(s) minimizing their frozen time\n" " restore restore a process/tree\n" " check checks whether the kernel support is up-to-date\n" " exec execute a system call by other task\n" " page-server launch page server\n" " service launch service\n" " dedup remove duplicates in memory dump\n" " cpuinfo dump writes cpu information into image file\n" " cpuinfo check validates cpu information read from image file\n" ); if (usage_error) { pr_msg("\nTry -h|--help for more info\n"); return 1; } pr_msg("\n" "Dump/Restore options:\n" "\n" "* Generic:\n" " -t|--tree PID checkpoint a process tree identified by PID\n" " -d|--restore-detached detach after restore\n" " -S|--restore-sibling restore root task as sibling\n" " -s|--leave-stopped leave tasks in stopped state after checkpoint\n" " -R|--leave-running leave tasks in running state after checkpoint\n" " -D|--images-dir DIR directory for image files\n" " --pidfile FILE write root task, service or page-server pid to FILE\n" " -W|--work-dir DIR directory to cd and write logs/pidfiles/stats to\n" " (if not specified, value of --images-dir is used)\n" " --cpu-cap [CAP] require certain cpu capability. CAP: may be one of:\n" " 'cpu','fpu','all','ins','none'. To disable capability, prefix it with '^'.\n" " --exec-cmd execute the command specified after '--' on successful\n" " restore making it the parent of the restored process\n" " --freeze-cgroup\n" " use cgroup freezer to collect processes\n" "\n" "* Special resources support:\n" " -x|--" USK_EXT_PARAM "inode,.." " allow external unix connections (optionally can be assign socket's inode that allows one-sided dump)\n" " --" SK_EST_PARAM " checkpoint/restore established TCP connections\n" " -r|--root PATH change the root filesystem (when run in mount namespace)\n" " --evasive-devices use any path to a device file if the original one\n" " is inaccessible\n" " --veth-pair IN=OUT map inside veth device name to outside one\n" " can optionally append @<bridge-name> to OUT for moving\n" " the outside veth to the named bridge\n" " --link-remap allow one to link unlinked files back when possible\n" " --ghost-limit size specify maximum size of deleted file contents to be carried inside an image file\n" " --action-script FILE add an external action script\n" " -j|--" OPT_SHELL_JOB " allow one to dump and restore shell jobs\n" " -l|--" OPT_FILE_LOCKS " handle file locks, for safety, only used for container\n" " -L|--libdir path to a plugin directory (by default " CR_PLUGIN_DEFAULT ")\n" " --force-irmap force resolving names for inotify/fsnotify watches\n" " --irmap-scan-path FILE\n" " add a path the irmap hints to scan\n" " -M|--ext-mount-map KEY:VALUE\n" " add external mount mapping\n" " -M|--ext-mount-map auto\n" " attempt to autodetect external mount mapings\n" " --enable-external-sharing\n" " allow autoresolving mounts with external sharing\n" " --enable-external-masters\n" " allow autoresolving mounts with external masters\n" " --manage-cgroups [m] dump or restore cgroups the process is in usig mode:\n" " 'none', 'props', 'soft' (default), 'full' and 'strict'.\n" " --cgroup-root [controller:]/newroot\n" " change the root cgroup the controller will be\n" " installed into. No controller means that root is the\n" " default for all controllers not specified.\n" " --skip-mnt PATH ignore this mountpoint when dumping the mount namespace.\n" " --enable-fs FSNAMES a comma separated list of filesystem names or \"all\".\n" " force criu to (try to) dump/restore these filesystem's\n" " mountpoints even if fs is not supported.\n" "\n" "* Logging:\n" " -o|--log-file FILE log file name\n" " --log-pid enable per-process logging to separate FILE.pid files\n" " -v[NUM] set logging level (higher level means more output):\n" " -v1|-v - only errors and messages\n" " -v2|-vv - also warnings (default level)\n" " -v3|-vvv - also information messages and timestamps\n" " -v4|-vvvv - lots of debug\n" "\n" "* Memory dumping options:\n" " --track-mem turn on memory changes tracker in kernel\n" " --prev-images-dir DIR path to images from previous dump (relative to -D)\n" " --page-server send pages to page server (see options below as well)\n" " --auto-dedup when used on dump it will deduplicate \"old\" data in\n" " pages images of previous dump\n" " when used on restore, as soon as page is restored, it\n" " will be punched from the image.\n" "\n" "Page/Service server options:\n" " --address ADDR address of server or service\n" " --port PORT port of page server\n" " -d|--daemon run in the background after creating socket\n" "\n" "Other options:\n" " -h|--help show this text\n" " -V|--version show version\n" " --ms don't check not yet merged kernel features\n" ); return 0; opt_pid_missing: pr_msg("Error: pid not specified\n"); return 1; bad_arg: if (idx < 0) /* short option */ pr_msg("Error: invalid argument for -%c: %s\n", opt, optarg); else /* long option */ pr_msg("Error: invalid argument for --%s: %s\n", long_opts[idx].name, optarg); return 1; }
void do_ip_addr(int argc, char *argv[]) { struct option_info opts[3]; char *ip_addr, *host_addr; bool ip_addr_set, host_addr_set; struct sockaddr_in host; #ifdef CYGPKG_REDBOOT_NETWORKING_DNS char *dns_addr; bool dns_addr_set; #endif int num_opts; init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR, (void *)&ip_addr, (bool *)&ip_addr_set, "local IP address"); init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR, (void *)&host_addr, (bool *)&host_addr_set, "default server address"); num_opts = 2; #ifdef CYGPKG_REDBOOT_NETWORKING_DNS init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_STR, (void *)&dns_addr, (bool *)&dns_addr_set, "DNS server address"); num_opts++; #endif CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) { return; } if (ip_addr_set) { #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY char *slash_pos; /* see if the (optional) mask length was given */ if( (slash_pos = strchr(ip_addr, '/')) ) { int mask_len; unsigned long mask; *slash_pos = '\0'; slash_pos++; if( !parse_num(slash_pos, (unsigned long *)&mask_len, 0, 0) || mask_len <= 0 || mask_len > 32 ) { diag_printf("Invalid mask length: %s\n", slash_pos); return; } mask = htonl((0xffffffff << (32-mask_len))&0xffffffff); memcpy(&__local_ip_mask, &mask, 4); } #endif if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) { diag_printf("Invalid local IP address: %s\n", ip_addr); return; } // Of course, each address goes in its own place :-) memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr)); } if (host_addr_set) { if (!_gethostbyname(host_addr, (in_addr_t *)&host)) { diag_printf("Invalid server address: %s\n", host_addr); return; } my_bootp_info.bp_siaddr = host.sin_addr; } #ifdef CYGPKG_REDBOOT_NETWORKING_DNS if (dns_addr_set) { set_dns(dns_addr); } #endif show_addrs(); if (!have_net) { have_net = true; net_io_init(); } }
static void do_mcopy(int argc, char *argv[]) { struct option_info opts[6]; unsigned long src, dst, len, end; bool src_set, dst_set, len_set; bool sz32, sz16, sz8; int incr = 1; init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM, (void *)&src, (bool *)&src_set, "base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&len, (bool *)&len_set, "length"); init_opts(&opts[2], 'd', true, OPTION_ARG_TYPE_NUM, (void *)&dst, (bool *)&dst_set, "base address"); init_opts(&opts[3], '4', false, OPTION_ARG_TYPE_FLG, (void *)&sz32, (bool *)0, "copy 32 bit data"); init_opts(&opts[4], '2', false, OPTION_ARG_TYPE_FLG, (void *)&sz16, (bool *)0, "copy 16 bit data"); init_opts(&opts[5], '1', false, OPTION_ARG_TYPE_FLG, (void *)&sz8, (bool *)0, "copy 8 bit data"); if (!scan_opts(argc, argv, 1, opts, 6, 0, 0, "")) { return; } // Must have src, dst, len. No more than one size specifier. if (!src_set || !dst_set || !len_set || (sz32 + sz16 + sz8) > 1) { diag_printf("usage: mcopy -s <addr> -d <addr> -l <length> [-1|-2|-4]\n"); return; } // adjust incr and len for data size if (sz16) { len = (len + 1) & ~1; incr = 2; } else if (sz32 || !sz8) { len = (len + 3) & ~3; incr = 4; } end = src + len; // If overlapping areas, must copy backwards. if (dst > src && dst < (src + len)) { end = src - incr; src += (len - incr); dst += (len - incr); incr = -incr; } if (sz8) { while (src != end) { *(cyg_uint8 *)dst = *(cyg_uint8 *)src; src += incr; dst += incr; } } else if (sz16) { while (src != end) { *(cyg_uint16 *)dst = *(cyg_uint16 *)src; src += incr; dst += incr; } } else { // Default - 32 bits while (src != end) { *(cyg_uint32 *)dst = *(cyg_uint32 *)src; src += incr; dst += incr; } } }
void do_go(int argc, char *argv[]) { int i, cur, num_options; unsigned long entry; unsigned long oldints; bool wait_time_set; int wait_time, res; bool cache_enabled = false; #ifdef CYGPKG_IO_ETH_DRIVERS bool stop_net = false; #endif struct option_info opts[3]; char line[8]; hal_virtual_comm_table_t *__chan; __mem_fault_handler = 0; // Let GDB handle any faults directly entry = entry_address; // Default from last 'load' operation init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, (void *)&wait_time, (bool *)&wait_time_set, "wait timeout"); init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, (void *)&cache_enabled, (bool *)0, "go with caches enabled"); num_options = 2; #ifdef CYGPKG_IO_ETH_DRIVERS init_opts(&opts[2], 'n', false, OPTION_ARG_TYPE_FLG, (void *)&stop_net, (bool *)0, "go with network driver stopped"); num_options++; #endif CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address")) { return; } if (entry == (unsigned long)NO_MEMORY) { diag_printf("No entry point known - aborted\n"); return; } if (wait_time_set) { int script_timeout_ms = wait_time * 1000; #ifdef CYGSEM_REDBOOT_FLASH_CONFIG unsigned char *hold_script = script; script = (unsigned char *)0; #endif diag_printf("About to start execution at %p - abort with ^C within %d seconds\n", (void *)entry, wait_time); while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) { res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT); if (res == _GETS_CTRLC) { #ifdef CYGSEM_REDBOOT_FLASH_CONFIG script = hold_script; // Re-enable script #endif return; } script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT; } } // Mask interrupts on all channels cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); for (i = 0; i < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS; i++) { CYGACC_CALL_IF_SET_CONSOLE_COMM(i); __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CONTROL( *__chan, __COMMCTL_IRQ_DISABLE ); } CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH); #ifdef CYGPKG_IO_ETH_DRIVERS if (stop_net) eth_drv_stop(); #endif HAL_DISABLE_INTERRUPTS(oldints); HAL_DCACHE_SYNC(); if (!cache_enabled) { HAL_ICACHE_DISABLE(); HAL_DCACHE_DISABLE(); HAL_DCACHE_SYNC(); } HAL_ICACHE_INVALIDATE_ALL(); HAL_DCACHE_INVALIDATE_ALL(); // set up a temporary context that will take us to the trampoline HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, trampoline, 0); // switch context to trampoline HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end); // we get back here by way of return_to_redboot() // undo the changes we made before switching context if (!cache_enabled) { HAL_ICACHE_ENABLE(); HAL_DCACHE_ENABLE(); } CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH); HAL_RESTORE_INTERRUPTS(oldints); diag_printf("\nProgram completed with status %d\n", return_status); }
void do_displayTempVoltage(int argc, char *argv[]) { struct option_info opts[3]; bool continuous = false; bool peak = false; bool allRegs = false; bool opt058; bool opt057; opt058 = isOptionInstalled((cyg_uint16 *)P4205_BOARD_ID_STATUS, 0x58); opt057 = isOptionInstalled((cyg_uint16 *)P4205_BOARD_ID_STATUS, 0x57); /* Check for continuous flag */ init_opts(&opts[0], 'c', false, OPTION_ARG_TYPE_FLG, (void **)&continuous, (bool *)0, "View results once a second"); init_opts(&opts[1], 'p', false, OPTION_ARG_TYPE_FLG, (void **)&peak, (bool *)0, "View peak conditions"); init_opts(&opts[2], 'a', false, OPTION_ARG_TYPE_FLG, (void **)&allRegs, (bool *)0, "View contents of all registers"); scan_opts(argc, argv, 1, opts, 3, 0, 0, ""); do { /* Display Settings */ if (!peak && !allRegs) { #if 0 if ((values.ext_temp2_value == -128) && (values.ext_temp1_value == -128) && (values.int_temp_value == -128)) diag_printf("Error reading current settings, Cycle Power\n"); else #endif P4205PrintTempVoltage(); } else if (!peak) { diag_printf("ADM1024 #1 Register Settings\n"); ADM1024PrintAllRegisters(GT64260_CPU_REG_BASE, P4205_I2C_ADM1024_SADDR_1); diag_printf("ADM1024 #2 Register Settings\n"); ADM1024PrintAllRegisters(GT64260_CPU_REG_BASE, P4205_I2C_ADM1024_SADDR_2); } else /* peak */ { P4205_PEAK_TEMP_VOLTAGE *peakTbl = (P4205_PEAK_TEMP_VOLTAGE *)P4205_PEAK_TEMP_VOLT_VALUES; diag_printf("\n Peak Voltage and Temperature Settings\n"); #ifdef CYGPKG_LIBC_STDIO printf("+1.5V Min = %3.3f Max = %3.3f\n", peakTbl->plus_1_5v_min, peakTbl->plus_1_5v_max); if (opt057 | opt058) printf("+1.3V Min = %3.3f Max = %3.3f\n", peakTbl->plus_1_6v_min, peakTbl->plus_1_6v_max); else printf("+1.6V Min = %3.3f Max = %3.3f\n", peakTbl->plus_1_6v_min, peakTbl->plus_1_6v_max); printf("+1.8V Min = %3.3f Max = %3.3f\n", peakTbl->plus_1_8v_min, peakTbl->plus_1_8v_max); printf("+2.5V Min = %3.3f Max = %3.3f\n", peakTbl->plus_2_5v_min, peakTbl->plus_2_5v_max); printf("Adm1024 #1 +3.3V Min = %3.3f Max = %3.3f\n", peakTbl->plus_3_3v_min_0, peakTbl->plus_3_3v_max_0); printf("Adm1024 #2 +3.3V Min = %3.3f Max = %3.3f\n", peakTbl->plus_3_3v_min_1, peakTbl->plus_3_3v_max_1); printf("Adm1024 #1 +5V Min = %3.3f Max = %3.3f\n", peakTbl->plus_5v_min_0, peakTbl->plus_5v_max_0); printf("Adm1024 #2 +5V Min = %3.3f Max = %3.3f\n", peakTbl->plus_5v_min_1, peakTbl->plus_5v_max_1); printf("Adm1024 #1 +12V Min = %3.3f Max = %3.3f\n", peakTbl->plus_12v_min_0, peakTbl->plus_12v_max_0); printf("Adm1024 #2 +12V Min = %3.3f Max = %3.3f\n", peakTbl->plus_12v_min_1, peakTbl->plus_12v_max_1); #endif diag_printf("Adm1024 #1 Internal Temperature Peak Value = %3d %%C\n", peakTbl->int_temp_max_0); diag_printf("Adm1024 #2 Internal Temperature Peak Value = %3d %%C\n", peakTbl->int_temp_max_1); diag_printf("VIM A/B FPGA Temperature Peak Value = %3d %%C\n", peakTbl->vim_ab_fpga_temp_max_0); diag_printf("VIM C/D FPGA Temperature Peak Value = %3d %%C\n", peakTbl->vim_cd_fpga_temp_max_0); diag_printf("PCB Temperature Peak Value(near heat sink) = %3d %%C\n", peakTbl->pcb_temp_max_1); } /* If continuous readout, delay 1 second and update */ if (continuous) CYGACC_CALL_IF_DELAY_US(1000000); } while (continuous); }
void do_pciedit(int argc, char *argv[]) { struct option_info opts[5]; unsigned long device; unsigned long function; unsigned long offset; unsigned long value; unsigned int bus = 0; bool bus_set; bool device_set; bool function_set; bool offset_set; bool value_set; cyg_uint8 devfn; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void **)&bus, (bool *)&bus_set, "bus"); init_opts(&opts[1], 'd', true, OPTION_ARG_TYPE_NUM, (void **)&device, (bool *)&device_set, "device"); init_opts(&opts[2], 'f', true, OPTION_ARG_TYPE_NUM, (void **)&function, (bool *)&function_set, "function"); init_opts(&opts[3], 'o', true, OPTION_ARG_TYPE_NUM, (void **)&offset, (bool *)&offset_set, "offset"); init_opts(&opts[4], 'v', true, OPTION_ARG_TYPE_NUM, (void **)&value, (bool *)&value_set, "value"); if (!scan_opts(argc, argv, 1, opts, 5, 0, 0, "")) { return; } if (!bus_set) { diag_printf("Pedit what [bus]?\n"); return; } if (!device_set) { diag_printf("Pedit what [device]?\n"); return; } if (device > 32) { diag_printf("Invalid Device Number - %d\n", (unsigned int)device); return; } if (!function_set) { function = 0; function_set = true; } if (function > 7) { diag_printf("Invalid Function Number - %d\n", (unsigned int)function); return; } if (!offset_set) { diag_printf("Pedit what [offset]?\n"); return; } if (!value_set) { diag_printf("Pedit what [value]?\n"); return; } #if 0 /* If device number is on the secondary bus, set bus number to 1 */ if (device >= P4205_SERIAL_MEZZ_CFG_ADDR) bus = 1; #endif devfn = CYG_PCI_DEV_MAKE_DEVFN(device, function); cyg_pcihw_write_config_uint32(bus, devfn, offset, value); }
void do_load(int argc, char *argv[]) { int res, num_options; int i, err; bool verbose, raw; bool base_addr_set, mode_str_set; char *mode_str; #ifdef CYGPKG_REDBOOT_NETWORKING struct sockaddr_in host; bool hostname_set, port_set; unsigned int port; // int because it's an OPTION_ARG_TYPE_NUM, // but will be cast to short char *hostname; #endif bool decompress = false; int chan = -1; #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1 bool chan_set; #endif unsigned long base = 0; unsigned long end = 0; char type[4]; char *filename = 0; struct option_info opts[8]; connection_info_t info; getc_io_funcs_t *io = NULL; struct load_io_entry *io_tab; #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS bool spillover_ok = false; #endif #ifdef CYGPKG_REDBOOT_NETWORKING memset((char *)&host, 0, sizeof(host)); host.sin_len = sizeof(host); host.sin_family = AF_INET; host.sin_addr = my_bootp_info.bp_siaddr; host.sin_port = 0; #endif init_opts(&opts[0], 'v', false, OPTION_ARG_TYPE_FLG, (void *)&verbose, 0, "verbose"); init_opts(&opts[1], 'r', false, OPTION_ARG_TYPE_FLG, (void *)&raw, 0, "load raw data"); init_opts(&opts[2], 'b', true, OPTION_ARG_TYPE_NUM, (void *)&base, (bool *)&base_addr_set, "load address"); init_opts(&opts[3], 'm', true, OPTION_ARG_TYPE_STR, (void *)&mode_str, (bool *)&mode_str_set, "download mode (TFTP, xyzMODEM, or disk)"); num_options = 4; #if CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS > 1 init_opts(&opts[num_options], 'c', true, OPTION_ARG_TYPE_NUM, (void *)&chan, (bool *)&chan_set, "I/O channel"); num_options++; #endif #ifdef CYGPKG_REDBOOT_NETWORKING init_opts(&opts[num_options], 'h', true, OPTION_ARG_TYPE_STR, (void *)&hostname, (bool *)&hostname_set, "host name or IP address"); num_options++; init_opts(&opts[num_options], 'p', true, OPTION_ARG_TYPE_NUM, (void *)&port, (bool *)&port_set, "TCP port"); num_options++; #endif #ifdef CYGBLD_BUILD_REDBOOT_WITH_ZLIB init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG, (void *)&decompress, 0, "decompress"); num_options++; #endif CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 1, opts, num_options, (void *)&filename, OPTION_ARG_TYPE_STR, "file name")) { return; } #ifdef CYGPKG_REDBOOT_NETWORKING if (hostname_set) { ip_route_t rt; if (!_gethostbyname(hostname, (in_addr_t *)&host)) { diag_printf("Invalid host: %s\n", hostname); return; } /* check that the host can be accessed */ if (__arp_lookup((ip_addr_t *)&host.sin_addr, &rt) < 0) { diag_printf("Unable to reach host %s (%s)\n", hostname, inet_ntoa((in_addr_t *)&host)); return; } } if (port_set) host.sin_port = port; #endif if (chan >= CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS) { diag_printf("Invalid I/O channel: %d\n", chan); return; } if (mode_str_set) { for (io_tab = __RedBoot_LOAD_TAB__; io_tab != &__RedBoot_LOAD_TAB_END__; io_tab++) { if (strncasecmp(&mode_str[0], io_tab->name, strlen(&mode_str[0])) == 0) { io = io_tab->funcs; break; } } if (!io) { diag_printf("Invalid 'mode': %s. Valid modes are:", mode_str); for (io_tab = __RedBoot_LOAD_TAB__; io_tab != &__RedBoot_LOAD_TAB_END__; io_tab++) { diag_printf(" %s", io_tab->name); } diag_printf("\n"); } if (!io) { return; } verbose &= io_tab->can_verbose; if (io_tab->need_filename && !filename) { diag_printf("File name required\n"); diag_printf("usage: load %s\n", usage); return; } } else { char *which; io_tab = (struct load_io_entry *)NULL; // Default #ifdef CYGPKG_REDBOOT_NETWORKING #ifdef CYGSEM_REDBOOT_NET_TFTP_DOWNLOAD which = "TFTP"; io = &tftp_io; #elif defined(CYGSEM_REDBOOT_NET_HTTP_DOWNLOAD) which = "HTTP"; io = &http_io; #endif #endif #ifdef CYGPKG_REDBOOT_FILEIO // Make file I/O default if mounted if (fileio_mounted) { which = "file"; io = &fileio_io; } #endif if (!io) { #ifdef CYGBLD_BUILD_REDBOOT_WITH_XYZMODEM which = "Xmodem"; io = &xyzModem_io; verbose = false; #else diag_printf("No default protocol!\n"); return; #endif } diag_printf("Using default protocol (%s)\n", which); } #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS if (base_addr_set && !valid_address((unsigned char *)base)) { if (!verify_action("Specified address (%p) is not believed to be in RAM", (void*)base)) return; spillover_ok = true; } #endif if (raw && !base_addr_set) { diag_printf("Raw load requires a memory address\n"); return; } info.filename = filename; info.chan = chan; info.mode = io_tab ? io_tab->mode : 0; #ifdef CYGPKG_REDBOOT_NETWORKING info.server = &host; #endif res = redboot_getc_init(&info, io, verbose, decompress); if (res < 0) { return; } // Stream open, process the data if (raw) { unsigned char *mp = (unsigned char *)base; err = 0; while ((res = redboot_getc()) >= 0) { #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS if (!valid_address(mp) && !spillover_ok) { // Only if there is no need to stop the download // before printing output can we ask confirmation // questions. redboot_getc_terminate(true); diag_printf("*** Abort! RAW data spills over limit of user RAM at %p\n",(void*)mp); err = -1; break; } #endif *mp++ = res; } end = (unsigned long) mp; // Save load base/top load_address = base; load_address_end = end; entry_address = base; // best guess redboot_getc_terminate(false); if (0 == err) diag_printf("Raw file loaded %p-%p, assumed entry at %p\n", (void *)base, (void *)(end - 1), (void*)base); } else { // Read initial header - to determine file [image] type for (i = 0; i < sizeof(type); i++) { if ((res = redboot_getc()) < 0) { err = getc_info.err; break; } type[i] = res; } if (res >= 0) { redboot_getc_rewind(); // Restore header to stream // Treat data as some sort of executable image if (strncmp(&type[1], "ELF", 3) == 0) { end = load_elf_image(redboot_getc, base); } else { redboot_getc_terminate(true); diag_printf("Unrecognized image type: 0x%lx\n", *(unsigned long *)type); } } } redboot_getc_close(); // Clean up return; }
static void fis_load(int argc, char *argv[]) { char *name; struct fis_image_desc *img; CYG_ADDRESS mem_addr; bool mem_addr_set = false; bool show_cksum = false; struct option_info opts[3]; #if defined(CYGSEM_REDBOOT_FIS_CRC_CHECK) unsigned long cksum; #endif int num_options; #if defined(CYGPRI_REDBOOT_ZLIB_FLASH) || defined(CYGSEM_REDBOOT_FIS_CRC_CHECK) bool decompress = false; #endif void *err_addr; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void *)&mem_addr, (bool *)&mem_addr_set, "memory [load] base address"); init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, (void *)&show_cksum, (bool *)0, "display checksum"); num_options = 2; #ifdef CYGPRI_REDBOOT_ZLIB_FLASH init_opts(&opts[num_options], 'd', false, OPTION_ARG_TYPE_FLG, (void *)&decompress, 0, "decompress"); num_options++; #endif CYG_ASSERT(num_options <= NUM_ELEMS(opts), "Too many options"); if (!scan_opts(argc, argv, 2, opts, num_options, (void *)&name, OPTION_ARG_TYPE_STR, "image name")) { fis_usage("invalid arguments"); return; } if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) { diag_printf("No image '%s' found\n", name); return; } if (!mem_addr_set) { mem_addr = img->mem_base; } // Load image from FLASH into RAM #ifdef CYGSEM_REDBOOT_VALIDATE_USER_RAM_LOADS if (!valid_address((void *)mem_addr)) { diag_printf("Not a loadable image - try using -b ADDRESS option\n"); return; } #endif #ifdef CYGPRI_REDBOOT_ZLIB_FLASH if (decompress) { int err; _pipe_t fis_load_pipe; _pipe_t* p = &fis_load_pipe; p->out_buf = (unsigned char*) mem_addr; p->out_max = p->out_size = -1; p->in_buf = (unsigned char*) img->flash_base; p->in_avail = img->data_length; err = (*_dc_init)(p); if (0 == err) err = (*_dc_inflate)(p); // Free used resources, do final translation of // error value. err = (*_dc_close)(p, err); if (0 != err && p->msg) { diag_printf("decompression error: %s\n", p->msg); } else { diag_printf("Image loaded from %p-%p\n", (unsigned char *)mem_addr, p->out_buf); } // Set load address/top load_address = mem_addr; load_address_end = (unsigned long)p->out_buf; // Reload fis directory fis_read_directory(); } else // dangling block #endif { flash_read((void *)img->flash_base, (void *)mem_addr, img->size, (void **)&err_addr); // Set load address/top load_address = mem_addr; load_address_end = mem_addr + img->size; diag_printf("load address 0x%08lx end 0x%08lx, image length 0x%08lx\n",load_address,load_address_end,img->data_length); } entry_address = (unsigned long)img->entry_point; #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length); if (show_cksum) { diag_printf("Checksum: 0x%08lx\n", cksum); } // When decompressing, leave CRC checking to decompressor if (!decompress && img->file_cksum) { if (cksum != img->file_cksum) { diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n", img->file_cksum, cksum); entry_address = (unsigned long)NO_MEMORY; } } #endif }
static void do_ping(int argc, char *argv[]) { struct option_info opts[7]; long count, timeout, length, rate, start_time, end_time, timer, received, tries; char *local_ip_addr, *host_ip_addr; bool local_ip_addr_set, host_ip_addr_set, count_set, timeout_set, length_set, rate_set, verbose; struct sockaddr_in local_addr, host_addr; ip_addr_t hold_addr; icmp_header_t *icmp; pktbuf_t *pkt; ip_header_t *ip; unsigned short cksum; ip_route_t dest_ip; init_opts(&opts[0], 'n', true, OPTION_ARG_TYPE_NUM, (void *)&count, (bool *)&count_set, "<count> - number of packets to test"); init_opts(&opts[1], 't', true, OPTION_ARG_TYPE_NUM, (void *)&timeout, (bool *)&timeout_set, "<timeout> - max #ms per packet [rount trip]"); init_opts(&opts[2], 'i', true, OPTION_ARG_TYPE_STR, (void *)&local_ip_addr, (bool *)&local_ip_addr_set, "local IP address"); init_opts(&opts[3], 'h', true, OPTION_ARG_TYPE_STR, (void *)&host_ip_addr, (bool *)&host_ip_addr_set, "host name or IP address"); init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "<length> - size of payload"); init_opts(&opts[5], 'v', false, OPTION_ARG_TYPE_FLG, (void *)&verbose, (bool *)0, "verbose operation"); init_opts(&opts[6], 'r', true, OPTION_ARG_TYPE_NUM, (void *)&rate, (bool *)&rate_set, "<rate> - time between packets"); if (!scan_opts(argc, argv, 1, opts, 7, (void **)0, 0, "")) { diag_printf("PING - Invalid option specified\n"); return; } // Set defaults; this has to be done _after_ the scan, since it will // have destroyed all values not explicitly set. if (local_ip_addr_set) { if (!_gethostbyname(local_ip_addr, (in_addr_t *)&local_addr)) { diag_printf("PING - Invalid local name: %s\n", local_ip_addr); return; } } else { memcpy((in_addr_t *)&local_addr, __local_ip_addr, sizeof(__local_ip_addr)); } if (host_ip_addr_set) { if (!_gethostbyname(host_ip_addr, (in_addr_t *)&host_addr)) { diag_printf("PING - Invalid host name: %s\n", host_ip_addr); return; } if (__arp_lookup((ip_addr_t *)&host_addr.sin_addr, &dest_ip) < 0) { diag_printf("PING: Cannot reach server '%s' (%s)\n", host_ip_addr, inet_ntoa((in_addr_t *)&host_addr)); return; } } else { diag_printf("PING - host name or IP address required\n"); return; } #define DEFAULT_LENGTH 64 #define DEFAULT_COUNT 10 #define DEFAULT_TIMEOUT 1000 #define DEFAULT_RATE 1000 if (!rate_set) { rate = DEFAULT_RATE; } if (!length_set) { length = DEFAULT_LENGTH; } if ((length < 64) || (length > 1400)) { diag_printf("Invalid length specified: %ld\n", length); return; } if (!count_set) { count = DEFAULT_COUNT; } if (!timeout_set) { timeout = DEFAULT_TIMEOUT; } // Note: two prints here because 'inet_ntoa' returns a static pointer diag_printf("Network PING - from %s", inet_ntoa((in_addr_t *)&local_addr)); diag_printf(" to %s\n", inet_ntoa((in_addr_t *)&host_addr)); received = 0; __icmp_install_listener(handle_icmp); // Save default "local" address memcpy(hold_addr, __local_ip_addr, sizeof(hold_addr)); for (tries = 0; tries < count; tries++) { // The network stack uses the global variable '__local_ip_addr' memcpy(__local_ip_addr, &local_addr, sizeof(__local_ip_addr)); // Build 'ping' request if ((pkt = __pktbuf_alloc(ETH_MAX_PKTLEN)) == NULL) { // Give up if no packets - something is wrong break; } icmp = pkt->icmp_hdr; ip = pkt->ip_hdr; pkt->pkt_bytes = length + sizeof(icmp_header_t); icmp->type = ICMP_TYPE_ECHOREQUEST; icmp->code = 0; icmp->checksum = 0; icmp->seqnum = htons(tries+1); cksum = __sum((word *)icmp, pkt->pkt_bytes, 0); icmp->checksum = htons(cksum); memcpy(ip->source, (in_addr_t *)&local_addr, sizeof(ip_addr_t)); memcpy(ip->destination, (in_addr_t *)&host_addr, sizeof(ip_addr_t)); ip->protocol = IP_PROTO_ICMP; ip->length = htons(pkt->pkt_bytes); __ip_send(pkt, IP_PROTO_ICMP, &dest_ip); __pktbuf_free(pkt); start_time = MS_TICKS(); timer = start_time + timeout; icmp_received = false; while (!icmp_received && (MS_TICKS_DELAY() < timer)) { if (_rb_break(1)) { goto abort; } MS_TICKS_DELAY(); __enet_poll(); } end_time = MS_TICKS(); timer = MS_TICKS() + rate; while (MS_TICKS_DELAY() < timer) { if (_rb_break(1)) { goto abort; } MS_TICKS_DELAY(); __enet_poll(); } if (icmp_received) { received++; if (verbose) { diag_printf(" seq: %d, time: %ld (ticks)\n", ntohs(hold_hdr.seqnum), end_time-start_time); } } } abort: __icmp_remove_listener(); // Clean up memcpy(__local_ip_addr, &hold_addr, sizeof(__local_ip_addr)); // Report diag_printf("PING - received %ld of %ld expected\n", received, count); }
static void fis_write(int argc, char *argv[]) { int stat; unsigned long length; CYG_ADDRESS mem_addr, flash_addr; bool mem_addr_set = false; bool flash_addr_set = false; bool length_set = false; void *err_addr; struct option_info opts[3]; bool prog_ok; init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM, (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "image length [in FLASH]"); if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0)) { fis_usage("invalid arguments"); return; } if (!mem_addr_set || !flash_addr_set || !length_set) { fis_usage("required parameter missing"); return; } // Round up length to FLASH block size #ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size; #endif if (flash_addr_set && ((stat = flash_verify_addr((void *)flash_addr)) || (stat = flash_verify_addr((void *)(flash_addr+length-1))))) { _show_invalid_flash_address(flash_addr, stat); return; } if (flash_addr_set && flash_addr & (flash_block_size-1)) { diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr); diag_printf(" must be 0x%x aligned\n", flash_block_size); return; } if ((mem_addr < (CYG_ADDRESS)ram_start) || ((mem_addr+length) >= (CYG_ADDRESS)ram_end)) { diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr); diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end); } // Safety check - make sure the address range is not within the code we're running if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) { diag_printf("Can't program this region - contains code in use!\n"); return; } if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p", (void *)flash_addr, (void *)(flash_addr+length-1), (void *)mem_addr)) { return; // The guy gave up } prog_ok = true; if (prog_ok) { // Erase area to be programmed if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) { diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat)); prog_ok = false; } } if (prog_ok) { // Now program it if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); prog_ok = false; } } }
static void do_write(int argc, char * argv[]) { char *name_str = NULL; int err; struct option_info opts[2]; CYG_ADDRESS mem_addr = 0; unsigned long length = 0; bool mem_addr_set = false; bool length_set = false; int fd; if( mount_count == 0 ) { err_printf("fs: No filesystems mounted\n"); return; } init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM, (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "image length"); if (!scan_opts(argc, argv, 1, opts, 2, &name_str, OPTION_ARG_TYPE_STR, "file name") || name_str == NULL) { fs_usage("invalid arguments"); return; } // diag_printf("load_address %08x %08x\n",load_address,load_address_end); // diag_printf("ram %08x %08x\n",ram_start, ram_end); // diag_printf("file name %08x >%s<\n",name_str,name_str); if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) && ((load_address_end) < (CYG_ADDRESS)ram_end)) { mem_addr = load_address; mem_addr_set = true; if (!length_set) { length = load_address_end - load_address; length_set = true; // maybe get length from existing file size if no loaded // image? } } fd = open( name_str, O_WRONLY|O_CREAT|O_TRUNC ); if( fd < 0 ) { err_printf("fs write: Cannot open %s\n", name_str ); return; } // diag_printf("write %08x %08x\n",mem_addr, length ); err = write( fd, (void *)mem_addr, length ); if( err != length ) { err_printf("fs write: failed to write to file %d(%d) %d\n",err,length,errno); } err = close( fd ); if( err != 0 ) err_printf("fs write: close failed\n"); }
static void fis_init(int argc, char *argv[]) { int stat; struct fis_image_desc *img; void *err_addr; bool full_init = false; struct option_info opts[1]; CYG_ADDRESS redboot_flash_start; unsigned long redboot_image_size; init_opts(&opts[0], 'f', false, OPTION_ARG_TYPE_FLG, (void *)&full_init, (bool *)0, "full initialization, erases all of flash"); if (!scan_opts(argc, argv, 2, opts, 1, 0, 0, "")) { return; } if (!verify_action("About to initialize [format] FLASH image system")) { diag_printf("** Aborted\n"); return; } diag_printf("*** Initialize FLASH Image System\n"); #define MIN_REDBOOT_IMAGE_SIZE CYGBLD_REDBOOT_MIN_IMAGE_SIZE redboot_image_size = flash_block_size > MIN_REDBOOT_IMAGE_SIZE ? flash_block_size : MIN_REDBOOT_IMAGE_SIZE; // Create a pseudo image for RedBoot img = (struct fis_image_desc *)fis_work_block; memset(img, 0xFF, fisdir_size); // Start with erased data #ifdef CYGOPT_REDBOOT_FIS_RESERVED_BASE memset(img, 0, sizeof(*img)); strcpy(img->name, "(reserved)"); img->flash_base = (CYG_ADDRESS)flash_start; img->mem_base = (CYG_ADDRESS)flash_start; img->size = CYGNUM_REDBOOT_FLASH_RESERVED_BASE; img++; #endif redboot_flash_start = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; #ifdef CYGOPT_REDBOOT_FIS_REDBOOT memset(img, 0, sizeof(*img)); strcpy(img->name, "RedBoot"); img->flash_base = redboot_flash_start; img->mem_base = redboot_flash_start; img->size = redboot_image_size; img++; redboot_flash_start += redboot_image_size; #endif #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_POST #ifdef CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET // Take care to place the POST entry at the right offset: redboot_flash_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FIS_REDBOOT_POST_OFFSET; #endif memset(img, 0, sizeof(*img)); strcpy(img->name, "RedBoot[post]"); img->flash_base = redboot_flash_start; img->mem_base = redboot_flash_start; img->size = redboot_image_size; img++; redboot_flash_start += redboot_image_size; #endif #ifdef CYGOPT_REDBOOT_FIS_REDBOOT_BACKUP // And a backup image memset(img, 0, sizeof(*img)); strcpy(img->name, "RedBoot[backup]"); img->flash_base = redboot_flash_start; img->mem_base = redboot_flash_start; img->size = redboot_image_size; img++; redboot_flash_start += redboot_image_size; #endif #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) // And a descriptor for the configuration data memset(img, 0, sizeof(*img)); strcpy(img->name, "RedBoot config"); img->flash_base = (CYG_ADDRESS)cfg_base; img->mem_base = (CYG_ADDRESS)cfg_base; img->size = cfg_size; img++; #endif // And a descriptor for the descriptor table itself memset(img, 0, sizeof(*img)); strcpy(img->name, "FIS directory"); img->flash_base = (CYG_ADDRESS)fis_addr; img->mem_base = (CYG_ADDRESS)fis_addr; img->size = fisdir_size; img++; #ifdef CYGOPT_REDBOOT_FIS_DIRECTORY_ARM_SIB_ID // FIS gets the size of a full block - note, this should be changed // if support is added for multi-block FIS structures. img = (struct fis_image_desc *)((CYG_ADDRESS)fis_work_block + fisdir_size); // Add a footer so the FIS will be recognized by the ARM Boot // Monitor as a reserved area. { tFooter* footer_p = (tFooter*)((CYG_ADDRESS)img - sizeof(tFooter)); cyg_uint32 check = 0; cyg_uint32 *check_ptr = (cyg_uint32 *)footer_p; cyg_int32 count = (sizeof(tFooter) - 4) >> 2; // Prepare footer. Try to protect all but the reserved space // and the first RedBoot image (which is expected to be // bootable), but fall back to just protecting the FIS if it's // not at the default position in the flash. #if defined(CYGOPT_REDBOOT_FIS_RESERVED_BASE) && (-1 == CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK) footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(flash_start); footer_p->blockBase += CYGNUM_REDBOOT_FLASH_RESERVED_BASE + redboot_image_size; #else footer_p->blockBase = (char*)_ADDR_REDBOOT_TO_ARM(fis_work_block); #endif footer_p->infoBase = NULL; footer_p->signature = FLASH_FOOTER_SIGNATURE; footer_p->type = TYPE_REDHAT_REDBOOT; // and compute its checksum for ( ; count > 0; count--) { if (*check_ptr > ~check) check++; check += *check_ptr++; } footer_p->checksum = ~check; } #endif // Do this after creating the initialized table because that inherently // calculates where the high water mark of default RedBoot images is. if (full_init) { unsigned long erase_size; CYG_ADDRESS erase_start; // Erase everything except default RedBoot images, fis block, // and config block. // First deal with the possible first part, before RedBoot images: #if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE) erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE; erase_size = (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET; if ( erase_size > erase_start ) { erase_size -= erase_start; if ((stat = flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) { diag_printf(" initialization failed at %p: %s\n", err_addr, flash_errmsg(stat)); } } #endif // second deal with the larger part in the main: erase_start = redboot_flash_start; // high water of created images // Now the empty bits between the end of Redboot and the cfg and dir // blocks. #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && \ defined(CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH) && \ !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG) if (fis_addr > cfg_base) { erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data } else { erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data } if ((stat = flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) { diag_printf(" initialization failed %p: %s\n", err_addr, flash_errmsg(stat)); } erase_start += (erase_size + flash_block_size); if (fis_addr > cfg_base) { erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data } else { erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data } if ((stat = flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) { diag_printf(" initialization failed %p: %s\n", err_addr, flash_errmsg(stat)); } erase_start += (erase_size + flash_block_size); #else // !CYGSEM_REDBOOT_FLASH_CONFIG erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data if ((stat = flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) { diag_printf(" initialization failed %p: %s\n", err_addr, flash_errmsg(stat)); } erase_start += (erase_size + flash_block_size); #endif // Lastly, anything at the end, if there is any if ( erase_start < (((CYG_ADDRESS)flash_end)+1) ) { erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1; if ((stat = flash_erase((void *)erase_start, erase_size, (void **)&err_addr)) != 0) { diag_printf(" initialization failed at %p: %s\n", err_addr, flash_errmsg(stat)); } } #ifndef CYGDAT_REDBOOT_FIS_MAX_FREE_CHUNKS // In this case, 'fis free' works by scanning for erased blocks. Since the // "-f" option was not supplied, there may be areas which are not used but // don't appear to be free since they are not erased - thus the warning } else { diag_printf(" Warning: device contents not erased, some blocks may not be usable\n"); #endif } fis_update_directory(); }
static void do_mem(int argc, char *argv[]) { struct option_info opts[4]; bool mem_half_word, mem_byte; bool no_verify = false; static int address = 0x00000000; int value; init_opts(&opts[0], 'b', false, OPTION_ARG_TYPE_FLG, (void**)&mem_byte, 0, "write a byte"); init_opts(&opts[1], 'h', false, OPTION_ARG_TYPE_FLG, (void**)&mem_half_word, 0, "write a half-word"); init_opts(&opts[2], 'a', true, OPTION_ARG_TYPE_NUM, (void**)&address, NULL, "address to write at"); init_opts(&opts[3], 'n', false, OPTION_ARG_TYPE_FLG, (void**)&no_verify, 0, "noverify"); if (!scan_opts(argc, argv, 1, opts, sizeof(opts) / sizeof(opts[0]), (void*)&value, OPTION_ARG_TYPE_NUM, "address to set")) { return; } if ( mem_byte && mem_half_word ) { diag_printf("*ERR: Should not specify both byte and half-word access\n"); } else if ( mem_byte ) { *(cyg_uint8*)address = (cyg_uint8)(value & 255); if (no_verify) { diag_printf(" Set 0x%08X to 0x%02X\n", address, value & 255); } else { diag_printf(" Set 0x%08X to 0x%02X (result 0x%02X)\n", address, value & 255, (int)*(cyg_uint8*)address ); } } else if ( mem_half_word ) { if ( address & 1 ) { diag_printf( "*ERR: Badly aligned address 0x%08X for half-word store\n", address ); } else { *(cyg_uint16*)address = (cyg_uint16)(value & 0xffff); if (no_verify) { diag_printf(" Set 0x%08X to 0x%04X\n", address, value & 0xffff); } else { diag_printf(" Set 0x%08X to 0x%04X (result 0x%04X)\n", address, value & 0xffff, (int)*(cyg_uint16*)address ); } } } else { if ( address & 3 ) { diag_printf( "*ERR: Badly aligned address 0x%08X for word store\n", address ); } else { *(cyg_uint32*)address = (cyg_uint32)value; if (no_verify) { diag_printf(" Set 0x%08X to 0x%08X\n", address, value); } else { diag_printf(" Set 0x%08X to 0x%08X (result 0x%08X)\n", address, value, (int)*(cyg_uint32*)address ); } } } }
static void fis_list(int argc, char *argv[]) { struct fis_image_desc *img; int i, image_indx; bool show_cksums = false; bool show_datalen = false; struct option_info opts[2]; unsigned long last_addr, lowest_addr; bool image_found; #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB // FIXME: this is somewhat half-baked extern void arm_fis_list(void); arm_fis_list(); return; #endif init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG, (void *)&show_datalen, (bool *)0, "display data length"); #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, (void *)&show_cksums, (bool *)0, "display checksums"); i = 2; #else i = 1; #endif if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) { return; } fis_read_directory(); // Let diag_printf do the formatting in both cases, rather than counting // cols by hand.... diag_printf("%-16s %-10s %-10s %-10s %-s\n", "Name","FLASH addr", show_cksums ? "Checksum" : "Mem addr", show_datalen ? "Datalen" : "Length", "Entry point" ); last_addr = 0; image_indx = 0; do { image_found = false; lowest_addr = 0xFFFFFFFF; img = (struct fis_image_desc *) fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { if (img->name[0] != (unsigned char)0xFF) { if ((img->flash_base > last_addr) && (img->flash_base < lowest_addr)) { lowest_addr = img->flash_base; image_found = true; image_indx = i; } } } if (image_found) { img = (struct fis_image_desc *) fis_work_block; img += image_indx; diag_printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", img->name, img->flash_base, #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK show_cksums ? img->file_cksum : img->mem_base, show_datalen ? img->data_length : img->size, #else img->mem_base, img->size, #endif img->entry_point); } last_addr = lowest_addr; } while (image_found == true); }
int cr_service(bool daemon_mode) { int server_fd = -1; int child_pid; struct sockaddr_un client_addr; socklen_t client_addr_len; { struct sockaddr_un server_addr; socklen_t server_addr_len; server_fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0); if (server_fd == -1) { pr_perror("Can't initialize service socket"); goto err; } memset(&server_addr, 0, sizeof(server_addr)); memset(&client_addr, 0, sizeof(client_addr)); server_addr.sun_family = AF_LOCAL; if (opts.addr == NULL) { pr_warn("Binding to local dir address!\n"); opts.addr = CR_DEFAULT_SERVICE_ADDRESS; } strcpy(server_addr.sun_path, opts.addr); server_addr_len = strlen(server_addr.sun_path) + sizeof(server_addr.sun_family); client_addr_len = sizeof(client_addr); unlink(server_addr.sun_path); if (bind(server_fd, (struct sockaddr *) &server_addr, server_addr_len) == -1) { pr_perror("Can't bind"); goto err; } pr_info("The service socket is bound to %s\n", server_addr.sun_path); /* change service socket permissions, so anyone can connect to it */ if (chmod(server_addr.sun_path, 0666)) { pr_perror("Can't change permissions of the service socket"); goto err; } if (listen(server_fd, 16) == -1) { pr_perror("Can't listen for socket connections"); goto err; } } if (daemon_mode) { if (daemon(1, 0) == -1) { pr_perror("Can't run service server in the background"); goto err; } } if (opts.pidfile) { if (write_pidfile(getpid()) == -1) { pr_perror("Can't write pidfile"); goto err; } } if (setup_sigchld_handler()) goto err; while (1) { int sk; pr_info("Waiting for connection...\n"); sk = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len); if (sk == -1) { pr_perror("Can't accept connection"); goto err; } pr_info("Connected.\n"); child_pid = fork(); if (child_pid == 0) { int ret; if (restore_sigchld_handler()) exit(1); close(server_fd); init_opts(); ret = cr_service_work(sk); close(sk); exit(ret != 0); } if (child_pid < 0) pr_perror("Can't fork a child"); close(sk); } err: close_safe(&server_fd); return 1; }
void do_go(int argc, char *argv[]) { unsigned long entry; unsigned long oldints; bool wait_time_set; int wait_time, res; bool cache_enabled = false; struct option_info opts[2]; char line[8]; hal_virtual_comm_table_t *__chan = CYGACC_CALL_IF_CONSOLE_PROCS(); entry = entry_address; // Default from last 'load' operation init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM, (void **)&wait_time, (bool *)&wait_time_set, "wait timeout"); init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG, (void **)&cache_enabled, (bool *)0, "go with caches enabled"); if (!scan_opts(argc, argv, 1, opts, 2, (void *)&entry, OPTION_ARG_TYPE_NUM, "starting address")) { return; } if (wait_time_set) { int script_timeout_ms = wait_time * 1000; #ifdef CYGSEM_REDBOOT_FLASH_CONFIG unsigned char *hold_script = script; script = (unsigned char *)0; #endif diag_printf("About to start execution at %p - abort with ^C within %d seconds\n", (void *)entry, wait_time); while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) { res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT); if (res == _GETS_CTRLC) { #ifdef CYGSEM_REDBOOT_FLASH_CONFIG script = hold_script; // Re-enable script #endif return; } script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT; } } CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_ENABLE_LINE_FLUSH); HAL_DISABLE_INTERRUPTS(oldints); HAL_DCACHE_SYNC(); if (!cache_enabled) { HAL_ICACHE_DISABLE(); HAL_DCACHE_DISABLE(); HAL_DCACHE_SYNC(); } HAL_ICACHE_INVALIDATE_ALL(); HAL_DCACHE_INVALIDATE_ALL(); // set up a temporary context that will take us to the trampoline HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, go_trampoline, 0); // switch context to trampoline HAL_THREAD_SWITCH_CONTEXT(&go_saved_context, &workspace_end); // we get back here by way of return_to_redboot() // undo the changes we made before switching context if (!cache_enabled) { HAL_ICACHE_ENABLE(); HAL_DCACHE_ENABLE(); } CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DISABLE_LINE_FLUSH); HAL_RESTORE_INTERRUPTS(oldints); diag_printf("\nProgram completed with status %d\n", go_return_status); }