Exemple #1
0
void cli_init(void)
{
#ifdef CONFIG_SYS_HUSH_PARSER
	u_boot_hush_start();
#endif

#if defined(CONFIG_HUSH_INIT_VAR)
	hush_init_var();
#endif
}
/*
 * this is called from board_init() after the hardware has been set up
 * and is usable. That seems like a good time to do this.
 * Right now the return value is ignored.
 */
int
do_auto_update(void)
{
	block_dev_desc_t *stor_dev;
	long sz;
	int i, res = 0, bitmap_first, cnt, old_ctrlc, got_ctrlc;
	char *env;
	long start, end;

#undef ERASE_EEPROM
#ifdef ERASE_EEPROM
	int arr[18];
	memset(arr, 0, sizeof(arr));
	i2c_write_multiple(0x54, 64, 1, arr, sizeof(arr));
#endif
	au_usb_stor_curr_dev = -1;
	/* start USB */
	if (usb_stop() < 0) {
		debug ("usb_stop failed\n");
		return -1;
	}
	if (usb_init() < 0) {
		debug ("usb_init failed\n");
		return -1;
	}
	/*
	 * check whether a storage device is attached (assume that it's
	 * a USB memory stick, since nothing else should be attached).
	 */
	au_usb_stor_curr_dev = usb_stor_scan(0);
	if (au_usb_stor_curr_dev == -1) {
		debug ("No device found. Not initialized?\n");
		res = -1;
		goto xit;
	}
	/* check whether it has a partition table */
	stor_dev = get_dev("usb", 0);
	if (stor_dev == NULL) {
		debug ("uknown device type\n");
		res = -1;
		goto xit;
	}
	if (fat_register_device(stor_dev, 1) != 0) {
		debug ("Unable to use USB %d:%d for fatls\n",
			au_usb_stor_curr_dev, 1);
		res = -1;
		goto xit;
	}
	if (file_fat_detectfs() != 0) {
		debug ("file_fat_detectfs failed\n");
	}

	/* initialize the array of file names */
	memset(aufile, 0, sizeof(aufile));
	aufile[IDX_PREPARE] = AU_PREPARE;
	aufile[IDX_PREINST] = AU_PREINST;
	aufile[IDX_FIRMWARE] = AU_FIRMWARE;
	aufile[IDX_KERNEL] = AU_KERNEL;
	aufile[IDX_APP] = AU_APP;
	aufile[IDX_DISK] = AU_DISK;
	aufile[IDX_POSTINST] = AU_POSTINST;
	/* initialize the array of flash sizes */
	memset(ausize, 0, sizeof(ausize));
	ausize[IDX_FIRMWARE] = (AU_FL_FIRMWARE_ND + 1) - AU_FL_FIRMWARE_ST;
	ausize[IDX_KERNEL] = (AU_FL_KERNEL_ND + 1) - AU_FL_KERNEL_ST;
	ausize[IDX_APP] = (AU_FL_APP_ND + 1) - AU_FL_APP_ST;
	ausize[IDX_DISK] = (AU_FL_DISK_ND + 1) - AU_FL_DISK_ST;
	/*
	 * now check whether start and end are defined using environment
	 * variables.
	 */
	start = -1;
	end = 0;
	env = getenv("firmware_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("firmware_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_FIRMWARE] = (end + 1) - start;
		aufl_layout[0].start = start;
		aufl_layout[0].end = end;
	}
	start = -1;
	end = 0;
	env = getenv("kernel_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("kernel_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_KERNEL] = (end + 1) - start;
		aufl_layout[1].start = start;
		aufl_layout[1].end = end;
	}
	start = -1;
	end = 0;
	env = getenv("app_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("app_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_APP] = (end + 1) - start;
		aufl_layout[2].start = start;
		aufl_layout[2].end = end;
	}
	start = -1;
	end = 0;
	env = getenv("disk_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("disk_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_DISK] = (end + 1) - start;
		aufl_layout[3].start = start;
		aufl_layout[3].end = end;
	}
	/* make certain that HUSH is runnable */
	u_boot_hush_start();
	/* make sure that we see CTRL-C and save the old state */
	old_ctrlc = disable_ctrlc(0);

	bitmap_first = 0;
	/* just loop thru all the possible files */
	for (i = 0; i < AU_MAXFILES; i++) {
		/* just read the header */
		sz = file_fat_read(aufile[i], LOAD_ADDR, image_get_header_size ());
		debug ("read %s sz %ld hdr %d\n",
			aufile[i], sz, image_get_header_size ());
		if (sz <= 0 || sz < image_get_header_size ()) {
			debug ("%s not found\n", aufile[i]);
			continue;
		}
		if (au_check_header_valid(i, sz) < 0) {
			debug ("%s header not valid\n", aufile[i]);
			continue;
		}
		sz = file_fat_read(aufile[i], LOAD_ADDR, MAX_LOADSZ);
		debug ("read %s sz %ld hdr %d\n",
			aufile[i], sz, image_get_header_size ());
		if (sz <= 0 || sz <= image_get_header_size ()) {
			debug ("%s not found\n", aufile[i]);
			continue;
		}
		if (au_check_cksum_valid(i, sz) < 0) {
			debug ("%s checksum not valid\n", aufile[i]);
			continue;
		}
#ifdef CONFIG_VFD
		/* now that we have a valid file we can display the */
		/* bitmap. */
		if (bitmap_first == 0) {
			env = getenv("bitmap2");
			if (env == NULL) {
				trab_vfd(0);
			} else {
				/* not so simple - bitmap2 is supposed to */
				/* contain the address of the bitmap */
				env = (char *)simple_strtoul(env, NULL, 16);
/* NOTE: these are taken from vfd_logo.h. If that file changes then */
/* these defines MUST also be updated! These may be wrong for bitmap2. */
#define VFD_LOGO_WIDTH 112
#define VFD_LOGO_HEIGHT 72
				/* must call transfer_pic directly */
				transfer_pic(3, (unsigned char *)env,
					     VFD_LOGO_HEIGHT, VFD_LOGO_WIDTH);
			}
			bitmap_first = 1;
		}
#endif
		/* this is really not a good idea, but it's what the */
		/* customer wants. */
		cnt = 0;
		got_ctrlc = 0;
		do {
			res = au_do_update(i, sz);
			/* let the user break out of the loop */
			if (ctrlc() || had_ctrlc()) {
				clear_ctrlc();
				if (res < 0)
					got_ctrlc = 1;
				break;
			}
			cnt++;
#ifdef AU_TEST_ONLY
		} while (res < 0 && cnt < 3);
		if (cnt < 3)
#else
		} while (res < 0);
#endif
		/*
		 * it doesn't make sense to update the EEPROM if the
		 * update was interrupted by the user due to errors.
		 */
		if (got_ctrlc == 0)
			au_update_eeprom(i);
		else
			/* enable the power switch */
			*CPLD_VFD_BK &= ~POWER_OFF;
	}
Exemple #3
0
void main_loop(void){
#ifndef CFG_HUSH_PARSER
	static char lastcommand[CFG_CBSIZE] = { 0, };
	int len;
	int rc = 1;
	int flag;
#endif
	int counter = 0;
	int stage=0;

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	char *s;
	int bootdelay;
#endif /* defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) */

#ifdef CFG_HUSH_PARSER
	u_boot_hush_start();
#endif

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	// get boot delay (seconds)
	s = getenv("bootdelay");
	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

	// get boot command
	s = getenv("bootcmd");

#if !defined(CONFIG_BOOTCOMMAND)
#error "CONFIG_BOOTCOMMAND not defined!"
#endif

	if(!s){
		setenv("bootcmd", CONFIG_BOOTCOMMAND);
	}

	s = getenv("bootcmd");

	// are we going to run web failsafe mode, U-Boot console, U-Boot netconsole or just boot command?
	if(reset_button_status()){

#ifdef CONFIG_SILENT_CONSOLE
		if(gd->flags & GD_FLG_SILENT){
			/* Restore serial console */
			console_assign(stdout, "serial");
			console_assign(stderr, "serial");
		}

		/* enable normal console output */
		gd->flags &= ~(GD_FLG_SILENT);
#endif

		all_led_off();
		// wait 0,5s
//		milisecdelay(500);

		printf("Press reset button for at least:\n"
			"- %d sec. to run upgrade from USB flash\n"
			"- %d sec. to run U-Boot console\n"
			"- %d sec. to run HTTP server\n"
			"- %d sec. to run netconsole\n\n",
				CONFIG_DELAY_TO_AUTORUN_USB,
				CONFIG_DELAY_TO_AUTORUN_CONSOLE,
				CONFIG_DELAY_TO_AUTORUN_HTTPD,
				CONFIG_DELAY_TO_AUTORUN_NETCONSOLE);

		printf("Reset button is pressed for: %2d ", counter);

		while(reset_button_status()){

			blink_sys_led(stage);	//	1 second!

			if(!reset_button_status()){
				break;
			}

			counter++;

			if(counter >= CONFIG_DELAY_TO_AUTORUN_USB)
			{
				if(counter >= CONFIG_DELAY_TO_AUTORUN_CONSOLE)
				{
					if(counter >= CONFIG_DELAY_TO_AUTORUN_HTTPD)
					{
						if(counter >= CONFIG_DELAY_TO_AUTORUN_NETCONSOLE)
						{
							stage=4;
						}
						else
						{
							stage=3;
						}
					}
					else
					{
						stage=2;
					}
				}
				else
				{
					stage=1;
				}
			}			

			// how long the button is pressed?
			printf("\b\b\b%2d ", counter);

			if(counter >= CONFIG_MAX_BUTTON_PRESSING){
				stage=0;	//	normal boot
				break;
			}
		}

		all_led_off();

		if(counter > 0){

			// run web failsafe mode
			if(stage == 1){
				printf("\n\nButton was pressed for %d sec...\nStarting upgrage from USB flash...\n\n", counter);
				bootdelay = -1;
				usb_upgrade();
			} else if(stage == 2){
				printf("\n\nButton was pressed for %d sec...\nStarting U-Boot console...\n\n", counter);
				bootdelay = -1;
			} else if(stage == 3){
				printf("\n\nButton was pressed for %d sec...\nHTTP server is starting for firmware update...\n\n", counter);
				NetLoopHttpd();
				bootdelay = -1;
			} else if(stage == 4){
				printf("\n\nButton was pressed for %d sec...\nStarting U-Boot netconsole...\n\n", counter);
				bootdelay = -1;
				run_command("startnc", 0);
			} else {
				printf("\n\n## Error: button wasn't pressed long enough!\nContinuing normal boot...\n\n");
			}

		} else {
			printf("\n\n## Error: button wasn't pressed long enough!\nContinuing normal boot...\n\n");
		}

	}

	if(bootdelay >= 0 && s && !abortboot(bootdelay)){

		try_runonce(1);

		try_autorun();

		try_runonce(2);

		// try to boot
#ifndef CFG_HUSH_PARSER
			run_command(s, 0);
#else
			parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
#endif

		// something goes wrong!
		printf("\n## Error: failed to execute 'bootcmd'!\nHTTP server is starting for firmware update...\n\n");
		NetLoopHttpd();
	}
#endif	/* CONFIG_BOOTDELAY */

	/*
	 * Main Loop for Monitor Command Processing
	 */
#ifdef CFG_HUSH_PARSER
	parse_file_outer();
	/* This point is never reached */
	for (;;);
#else
	for(;;){
		len = readline(CFG_PROMPT);

		flag = 0; /* assume no special flags for now */
		if(len > 0){
			strcpy(lastcommand, console_buffer);
		} else if(len == 0){
			flag |= CMD_FLAG_REPEAT;
		}

		if(len == -1){
			puts("<INTERRUPT>\n");
		} else {
			rc = run_command(lastcommand, flag);
		}

		if(rc <= 0){
			/* invalid command or not repeatable, forget it */
			lastcommand[0] = 0;
		}
	}
#endif /* CFG_HUSH_PARSER */
}
Exemple #4
0
/*
 * this is called from board_init() after the hardware has been set up
 * and is usable. That seems like a good time to do this.
 * Right now the return value is ignored.
 */
int do_auto_update(void)
{
	block_dev_desc_t *stor_dev;
	long sz;
	int i, res = 0, cnt, old_ctrlc;
	char *env;
	long start, end;

#if 0 /* disable key-press detection to speed up boot-up time */
	uchar keypad_status1[2] = {0,0}, keypad_status2[2] = {0,0};

	/*
	 * Read keypad status
	 */
	i2c_read(I2C_PSOC_KEYPAD_ADDR, 0, 0, keypad_status1, 2);
	mdelay(500);
	i2c_read(I2C_PSOC_KEYPAD_ADDR, 0, 0, keypad_status2, 2);

	/*
	 * Check keypad
	 */
	if ( !(keypad_status1[1] & KEYPAD_MASK_LO) ||
	      (keypad_status1[1] != keypad_status2[1])) {
		return 0;
	}

#endif
	au_usb_stor_curr_dev = -1;
	/* start USB */
	if (usb_stop() < 0) {
		debug ("usb_stop failed\n");
		return -1;
	}
	if (usb_init() < 0) {
		debug ("usb_init failed\n");
		return -1;
	}
	/*
	 * check whether a storage device is attached (assume that it's
	 * a USB memory stick, since nothing else should be attached).
	 */
	au_usb_stor_curr_dev = usb_stor_scan(0);
	if (au_usb_stor_curr_dev == -1) {
		debug ("No device found. Not initialized?\n");
		res = -1;
		goto xit;
	}
	/* check whether it has a partition table */
	stor_dev = get_dev("usb", 0);
	if (stor_dev == NULL) {
		debug ("uknown device type\n");
		res = -1;
		goto xit;
	}
	if (fat_register_device(stor_dev, 1) != 0) {
		debug ("Unable to use USB %d:%d for fatls\n",
			au_usb_stor_curr_dev, 1);
		res = -1;
		goto xit;
	}
	if (file_fat_detectfs() != 0) {
		debug ("file_fat_detectfs failed\n");
	}

	/*
	 * now check whether start and end are defined using environment
	 * variables.
	 */
	start = -1;
	end = 0;
	env = getenv("firmware_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("firmware_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_FIRMWARE] = (end + 1) - start;
		aufl_layout[IDX_FIRMWARE].start = start;
		aufl_layout[IDX_FIRMWARE].end = end;
	}
	start = -1;
	end = 0;
	env = getenv("kernel_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("kernel_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_KERNEL] = (end + 1) - start;
		aufl_layout[IDX_KERNEL].start = start;
		aufl_layout[IDX_KERNEL].end = end;
	}
	start = -1;
	end = 0;
	env = getenv("rootfs_st");
	if (env != NULL)
		start = simple_strtoul(env, NULL, 16);
	env = getenv("rootfs_nd");
	if (env != NULL)
		end = simple_strtoul(env, NULL, 16);
	if (start >= 0 && end && end > start) {
		ausize[IDX_ROOTFS] = (end + 1) - start;
		aufl_layout[IDX_ROOTFS].start = start;
		aufl_layout[IDX_ROOTFS].end = end;
	}

	/* make certain that HUSH is runnable */
	u_boot_hush_start();
	/* make sure that we see CTRL-C and save the old state */
	old_ctrlc = disable_ctrlc(0);

	/* validate the images first */
	for (i = 0; i < AU_MAXFILES; i++) {
		ulong imsize;
		/* just read the header */
		sz = file_fat_read(aufile[i], LOAD_ADDR, image_get_header_size ());
		debug ("read %s sz %ld hdr %d\n",
			aufile[i], sz, image_get_header_size ());
		if (sz <= 0 || sz < image_get_header_size ()) {
			debug ("%s not found\n", aufile[i]);
			ausize[i] = 0;
			continue;
		}
		/* au_check_header_valid() updates ausize[] */
		if ((imsize = au_check_header_valid(i, sz)) < 0) {
			debug ("%s header not valid\n", aufile[i]);
			continue;
		}
		/* totsize accounts for image size and flash erase size */
		totsize += (imsize + (aufl_layout[i].end - aufl_layout[i].start));
	}

#ifdef CONFIG_PROGRESSBAR
	if (totsize) {
		lcd_puts(" Update in progress\n");
		lcd_enable();
	}
#endif

	/* just loop thru all the possible files */
	for (i = 0; i < AU_MAXFILES && totsize; i++) {
		if (!ausize[i]) {
			continue;
		}
		sz = file_fat_read(aufile[i], LOAD_ADDR, ausize[i]);

		debug ("read %s sz %ld hdr %d\n",
			aufile[i], sz, image_get_header_size ());

		if (sz != ausize[i]) {
			printf ("%s: size %ld read %ld?\n", aufile[i], ausize[i], sz);
			continue;
		}

		if (sz <= 0 || sz <= image_get_header_size ()) {
			debug ("%s not found\n", aufile[i]);
			continue;
		}
		if (au_check_cksum_valid(i, sz) < 0) {
			debug ("%s checksum not valid\n", aufile[i]);
			continue;
		}
		/* this is really not a good idea, but it's what the */
		/* customer wants. */
		cnt = 0;
		do {
			res = au_do_update(i, sz);
			/* let the user break out of the loop */
			if (ctrlc() || had_ctrlc()) {
				clear_ctrlc();
				break;
			}
			cnt++;
#ifdef AU_TEST_ONLY
		} while (res < 0 && cnt < (AU_MAXFILES + 1));
		if (cnt < (AU_MAXFILES + 1))
#else
		} while (res < 0);
#endif
	}
Exemple #5
0
static __inline__ int abortboot(int bootdelay){
	char stopc;
	int abort = 0;

#ifdef CONFIG_SILENT_CONSOLE
	if(gd->flags & GD_FLG_SILENT){
		/* Restore serial console */
		console_assign(stdout, "serial");
		console_assign(stderr, "serial");
	}
#endif

	if(bootdelay > 0){
#ifdef CONFIG_MENUPROMPT
		printf(CONFIG_MENUPROMPT, bootdelay);
#else
		printf("Hit any key to stop autoboot: %d ", bootdelay);
#endif

		while((bootdelay > 0) && (!abort)){
			int i;

			--bootdelay;

			/* delay 100 * 10ms */
			for(i = 0; !abort && i < 100; ++i){
				/* we got a key press	*/
				if(tstc()){
					stopc = getc();
#ifdef CONFIG_AUTOBOOT_STOP_CHAR
					if (stopc == CONFIG_AUTOBOOT_STOP_CHAR) {
#else
					if (stopc != 0) {
#endif
						abort = 1;
						bootdelay = 0;

						break;
					}
				}
				udelay(10000);
			}

			printf("\b\b%d ", bootdelay);
		}

		printf("\n\n");
	}

#ifdef CONFIG_SILENT_CONSOLE
	if(abort){
		/* permanently enable normal console output */
		gd->flags &= ~(GD_FLG_SILENT);
	} else if(gd->flags & GD_FLG_SILENT){
		/* Restore silent console */
		console_assign(stdout, "nulldev");
		console_assign(stderr, "nulldev");
	}
#endif

	return(abort);
}
#endif	/* CONFIG_BOOTDELAY >= 0  */

/****************************************************************************/

void main_loop(void){
#ifndef CFG_HUSH_PARSER
	static char lastcommand[CFG_CBSIZE] = { 0, };
	int len;
	int rc = 1;
	int flag;
#endif
	int counter = 0;

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	char *s;
	int bootdelay;
#endif /* defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) */

#ifdef CFG_HUSH_PARSER
	u_boot_hush_start();
#endif

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	// get boot delay (seconds)
	s = getenv("bootdelay");
	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

	// get boot command
	s = getenv("bootcmd");

#if !defined(CONFIG_BOOTCOMMAND)
#error "CONFIG_BOOTCOMMAND not defined!"
#endif

	if(!s){
		setenv("bootcmd", CONFIG_BOOTCOMMAND);
	}

	s = getenv("bootcmd");

	// are we going to run web failsafe mode, U-Boot console, U-Boot netconsole or just boot command?
	if(reset_button_status()){

#ifdef CONFIG_SILENT_CONSOLE
		if(gd->flags & GD_FLG_SILENT){
			/* Restore serial console */
			console_assign(stdout, "serial");
			console_assign(stderr, "serial");
		}

		/* enable normal console output */
		gd->flags &= ~(GD_FLG_SILENT);
#endif

		// wait 0,5s
		milisecdelay(500);

		printf("Press reset button for at least:\n- %d sec. to run web failsafe mode\n- %d sec. to run U-Boot console\n- %d sec. to run U-Boot netconsole\n\n",
				CONFIG_DELAY_TO_AUTORUN_HTTPD,
				CONFIG_DELAY_TO_AUTORUN_CONSOLE,
				CONFIG_DELAY_TO_AUTORUN_NETCONSOLE);

		printf("Reset button is pressed for: %2d ", counter);

		while(reset_button_status()){

			// LED ON and wait 0,15s
			all_led_on();
			milisecdelay(150);

			// LED OFF and wait 0,85s
			all_led_off();
			milisecdelay(850);

			counter++;

			// how long the button is pressed?
			printf("\b\b\b%2d ", counter);

			if(!reset_button_status()){
				break;
			}

			if(counter >= CONFIG_MAX_BUTTON_PRESSING){
				break;
			}
		}

		all_led_off();

		if(counter > 0){

			// run web failsafe mode
			if(counter >= CONFIG_DELAY_TO_AUTORUN_HTTPD && counter < CONFIG_DELAY_TO_AUTORUN_CONSOLE){
				printf("\n\nButton was pressed for %d sec...\nHTTP server is starting for firmware update...\n\n", counter);
				NetLoopHttpd();
				bootdelay = -1;
			} else if(counter >= CONFIG_DELAY_TO_AUTORUN_CONSOLE && counter < CONFIG_DELAY_TO_AUTORUN_NETCONSOLE){
				printf("\n\nButton was pressed for %d sec...\nStarting U-Boot console...\n\n", counter);
				bootdelay = -1;
			} else if(counter >= CONFIG_DELAY_TO_AUTORUN_NETCONSOLE){
				printf("\n\nButton was pressed for %d sec...\nStarting U-Boot netconsole...\n\n", counter);
				bootdelay = -1;
				run_command("startnc", 0);
			} else {
				printf("\n\n## Error: button wasn't pressed long enough!\nContinuing normal boot...\n\n");
			}

		} else {
			printf("\n\n## Error: button wasn't pressed long enough!\nContinuing normal boot...\n\n");
		}

	}

	if(bootdelay >= 0 && s && !abortboot(bootdelay)){

		// try to boot
#ifndef CFG_HUSH_PARSER
			run_command(s, 0);
#else
			parse_string_outer(s, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
#endif

		// something goes wrong!
		printf("\n## Error: failed to execute 'bootcmd'!\nHTTP server is starting for firmware update...\n\n");
		NetLoopHttpd();
	}
#endif	/* CONFIG_BOOTDELAY */

	/*
	 * Main Loop for Monitor Command Processing
	 */
#ifdef CFG_HUSH_PARSER
	parse_file_outer();
	/* This point is never reached */
	for (;;);
#else
	for(;;){
		len = readline(CFG_PROMPT);

		flag = 0; /* assume no special flags for now */
		if(len > 0){
			strcpy(lastcommand, console_buffer);
		} else if(len == 0){
			flag |= CMD_FLAG_REPEAT;
		}

		if(len == -1){
			puts("<INTERRUPT>\n");
		} else {
			rc = run_command(lastcommand, flag);
		}

		if(rc <= 0){
			/* invalid command or not repeatable, forget it */
			lastcommand[0] = 0;
		}
	}
#endif /* CFG_HUSH_PARSER */
}

/****************************************************************************/

/*
 * Prompt for input and read a line.
 * If  CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
 * time out when time goes past endtime (timebase time in ticks).
 * Return:	number of read characters
 *		-1 if break
 *		-2 if timed out
 */
int readline(const char * const prompt){
	char *p = console_buffer;
	int n = 0; /* buffer index		*/
	int plen = 0; /* prompt length	*/
	int col; /* output column cnt	*/
	char c;

	/* print prompt */
	if(prompt){
		plen = strlen(prompt);
		puts(prompt);
	}
	col = plen;

	for(;;){
		c = getc();

		/*
		 * Special character handling
		 */
		switch(c){
			case '\r': /* Enter		*/
			case '\n':
				*p = '\0';
				puts("\r\n");
				return(p - console_buffer);

			case '\0': /* nul			*/
				continue;

			case 0x03: /* ^C - break		*/
				console_buffer[0] = '\0'; /* discard input */
				return(-1);

			case 0x15: /* ^U - erase line	*/
				while(col > plen){
					puts(erase_seq);
					--col;
				}
				p = console_buffer;
				n = 0;
				continue;

			case 0x17: /* ^W - erase word 	*/
				p = delete_char(console_buffer, p, &col, &n, plen);
				while((n > 0) && (*p != ' ')){
					p = delete_char(console_buffer, p, &col, &n, plen);
				}
				continue;

			case 0x08: /* ^H  - backspace	*/
			case 0x7F: /* DEL - backspace	*/
				p = delete_char(console_buffer, p, &col, &n, plen);
				continue;

			default:
				/*
				 * Must be a normal character then
				 */
				if(n < CFG_CBSIZE - 2){
					if(c == '\t'){ /* expand TABs		*/
						puts(tab_seq + (col & 07));
						col += 8 - (col & 07);
					} else {
						++col; /* echo input		*/
						putc(c);
					}
					*p++ = c;
					++n;
				} else { /* Buffer full		*/
					putc('\a');
				}
		}
	}
}