main.c

来自「嵌入式试验箱S3C2410的bootloader源代码」· C语言 代码 · 共 1,447 行 · 第 1/3 页

C
1,447
字号
/* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * Add to readline cmdline-editing by * (C) Copyright 2005 * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* #define	DEBUG	*/#include <common.h>#include <watchdog.h>#include <command.h>#ifdef CONFIG_MODEM_SUPPORT#include <malloc.h>		/* for free() prototype */#endif#ifdef CFG_HUSH_PARSER#include <hush.h>#endif#include <post.h>#ifdef CONFIG_SILENT_CONSOLEDECLARE_GLOBAL_DATA_PTR;#endif#if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY)extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);		/* for do_reset() prototype */#endifextern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);#define MAX_DELAY_STOP_STR 32static int parse_line (char *, char *[]);#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)static int abortboot(int);#endif#undef DEBUG_PARSERchar        console_buffer[CFG_CBSIZE];		/* console I/O buffer	*/#ifndef CONFIG_CMDLINE_EDITINGstatic char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);static char erase_seq[] = "\b \b";		/* erase sequence	*/static char   tab_seq[] = "        ";		/* used to expand TABs	*/#endif /* CONFIG_CMDLINE_EDITING */#ifdef CONFIG_BOOT_RETRY_TIMEstatic uint64_t endtime = 0;  /* must be set, default is instant timeout */static int      retry_time = -1; /* -1 so can call readline before main_loop */#endif#define	endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())#ifndef CONFIG_BOOT_RETRY_MIN#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME#endif#ifdef CONFIG_MODEM_SUPPORTint do_mdm_init = 0;extern void mdm_init(void); /* defined in board.c */#endif/*************************************************************************** * Watch for 'delay' seconds for autoboot stop or autoboot delay string. * returns: 0 -  no key string, allow autoboot *          1 - got key string, abort */#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)# if defined(CONFIG_AUTOBOOT_KEYED)static __inline__ int abortboot(int bootdelay){	int abort = 0;	uint64_t etime = endtick(bootdelay);	struct {		char* str;		u_int len;		int retry;	}	delaykey [] = {		{ str: getenv ("bootdelaykey"),  retry: 1 },		{ str: getenv ("bootdelaykey2"), retry: 1 },		{ str: getenv ("bootstopkey"),   retry: 0 },		{ str: getenv ("bootstopkey2"),  retry: 0 },	};	char presskey [MAX_DELAY_STOP_STR];	u_int presskey_len = 0;	u_int presskey_max = 0;	u_int i;#ifdef CONFIG_SILENT_CONSOLE	if (gd->flags & GD_FLG_SILENT) {		/* Restore serial console */		console_assign (stdout, "serial");		console_assign (stderr, "serial");	}#endif#  ifdef CONFIG_AUTOBOOT_PROMPT	printf (CONFIG_AUTOBOOT_PROMPT, bootdelay);#  endif#  ifdef CONFIG_AUTOBOOT_DELAY_STR	if (delaykey[0].str == NULL)		delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;#  endif#  ifdef CONFIG_AUTOBOOT_DELAY_STR2	if (delaykey[1].str == NULL)		delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2;#  endif#  ifdef CONFIG_AUTOBOOT_STOP_STR	if (delaykey[2].str == NULL)		delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR;#  endif#  ifdef CONFIG_AUTOBOOT_STOP_STR2	if (delaykey[3].str == NULL)		delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;#  endif	for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {		delaykey[i].len = delaykey[i].str == NULL ?				    0 : strlen (delaykey[i].str);		delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?				    MAX_DELAY_STOP_STR : delaykey[i].len;		presskey_max = presskey_max > delaykey[i].len ?				    presskey_max : delaykey[i].len;#  if DEBUG_BOOTKEYS		printf("%s key:<%s>\n",		       delaykey[i].retry ? "delay" : "stop",		       delaykey[i].str ? delaykey[i].str : "NULL");#  endif	}	/* In order to keep up with incoming data, check timeout only	 * when catch up.	 */	while (!abort && get_ticks() <= etime) {		for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {			if (delaykey[i].len > 0 &&			    presskey_len >= delaykey[i].len &&			    memcmp (presskey + presskey_len - delaykey[i].len,				    delaykey[i].str,				    delaykey[i].len) == 0) {#  if DEBUG_BOOTKEYS				printf("got %skey\n",				       delaykey[i].retry ? "delay" : "stop");#  endif#  ifdef CONFIG_BOOT_RETRY_TIME				/* don't retry auto boot */				if (! delaykey[i].retry)					retry_time = -1;#  endif				abort = 1;			}		}		if (tstc()) {			if (presskey_len < presskey_max) {				presskey [presskey_len ++] = getc();			}			else {				for (i = 0; i < presskey_max - 1; i ++)					presskey [i] = presskey [i + 1];				presskey [i] = getc();			}		}	}#  if DEBUG_BOOTKEYS	if (!abort)		puts ("key timeout\n");#  endif#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;}# else	/* !defined(CONFIG_AUTOBOOT_KEYED) */#ifdef CONFIG_MENUKEYstatic int menukey = 0;#endifstatic __inline__ int abortboot(int bootdelay){	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#ifdef CONFIG_MENUPROMPT	printf(CONFIG_MENUPROMPT, bootdelay);#else	printf("Hit any key to stop autoboot: %2d ", bootdelay);#endif#if defined CONFIG_ZERO_BOOTDELAY_CHECK	/*	 * Check if key already pressed	 * Don't check if bootdelay < 0	 */	if (bootdelay >= 0) {		if (tstc()) {	/* we got a key press	*/			(void) getc();  /* consume input	*/			puts ("\b\b\b 0");			abort = 1; 	/* don't auto boot	*/		}	}#endif	while ((bootdelay > 0) && (!abort)) {		int i;		--bootdelay;		/* delay 100 * 10ms */		for (i=0; !abort && i<100; ++i) {			if (tstc()) {	/* we got a key press	*/# ifdef CONFIG_MENUKEY				abort  = 1;	/* don't auto boot	*/				bootdelay = 0;	/* no more delay	*/				menukey = getc();				break;# else				/* consume input	*/				if (getc() == ' ') {					abort  = 1; /* don't auto boot	*/					bootdelay = 0;	/* no more delay	*/					break;				}# endif			}			udelay (10000);		}		printf ("\b\b\b%2d ", bootdelay);	}	putc ('\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_AUTOBOOT_KEYED */#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#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)	char *s;	int bootdelay;#endif#ifdef CONFIG_PREBOOT	char *p;#endif#ifdef CONFIG_BOOTCOUNT_LIMIT	unsigned long bootcount = 0;	unsigned long bootlimit = 0;	char *bcs;	char bcs_set[16];#endif /* CONFIG_BOOTCOUNT_LIMIT */#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)	ulong bmp = 0;		/* default bitmap */	extern int trab_vfd (ulong bitmap);#ifdef CONFIG_MODEM_SUPPORT	if (do_mdm_init)		bmp = 1;	/* alternate bitmap */#endif	trab_vfd (bmp);#endif	/* CONFIG_VFD && VFD_TEST_LOGO */#ifdef CONFIG_BOOTCOUNT_LIMIT	bootcount = bootcount_load();	bootcount++;	bootcount_store (bootcount);	sprintf (bcs_set, "%lu", bootcount);	setenv ("bootcount", bcs_set);	bcs = getenv ("bootlimit");	bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;#endif /* CONFIG_BOOTCOUNT_LIMIT */#ifdef CONFIG_MODEM_SUPPORT	debug ("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);	if (do_mdm_init) {		char *str = strdup(getenv("mdm_cmd"));		setenv ("preboot", str);  /* set or delete definition */		if (str != NULL)			free (str);		mdm_init(); /* wait for modem connection */	}#endif  /* CONFIG_MODEM_SUPPORT */#ifdef CONFIG_VERSION_VARIABLE	{		extern char version_string[];		setenv ("ver", version_string);  /* set version variable */	}#endif /* CONFIG_VERSION_VARIABLE */#ifdef CFG_HUSH_PARSER	u_boot_hush_start ();#endif#ifdef CONFIG_AUTO_COMPLETE	install_auto_complete();#endif#ifdef CONFIG_JFFS2_CMDLINE    extern int mtdparts_init(void);    if (!getenv("mtdparts"))    {        run_command("mtdparts default", 0);    }    else    {        mtdparts_init();    }#endif#ifdef CONFIG_PREBOOT	if ((p = getenv ("preboot")) != NULL) {# ifdef CONFIG_AUTOBOOT_KEYED		int prev = disable_ctrlc(1);	/* disable Control C checking */# endif# ifndef CFG_HUSH_PARSER		run_command (p, 0);# else		parse_string_outer(p, FLAG_PARSE_SEMICOLON |				    FLAG_EXIT_FROM_LOOP);# endif# ifdef CONFIG_AUTOBOOT_KEYED		disable_ctrlc(prev);	/* restore Control C checking */# endif	}#endif /* CONFIG_PREBOOT */#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)	s = getenv ("bootdelay");	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;	debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);# ifdef CONFIG_BOOT_RETRY_TIME	init_cmd_timeout ();# endif	/* CONFIG_BOOT_RETRY_TIME */	if (PreLoadedONRAM)	{		printf("Use these steps to program the image to flash:\n");		printf("1. In OpenOCD\n");		printf("   Run the 'halt' command to halt u-boot\n");		printf("   Run the 'load_image <file> <address>' command to load file to SDRAM\n");		printf("   Run the 'resume' command to resume u-boot\n");		printf("2. In u-boot, use the flash commands to program the image to flash\n");		printf("Or, use the tftp or nfs command to download file, and then program the flash.\n");		goto PROMPT;	}#ifdef CONFIG_BOOTCOUNT_LIMIT	if (bootlimit && (bootcount > bootlimit)) {		printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",		        (unsigned)bootlimit);		s = getenv ("altbootcmd");	}	else#endif /* CONFIG_BOOTCOUNT_LIMIT */		s = getenv ("bootcmd");	debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");	if (bootdelay >= 0 && s && !abortboot (bootdelay)) {# ifdef CONFIG_AUTOBOOT_KEYED		int prev = disable_ctrlc(1);	/* disable Control C checking */# endif# ifndef CFG_HUSH_PARSER#ifdef CONFIG_SURPORT_WINCE        if (!TOC_Read())        {            /* Launch wince */            char cmd_buf[16];            printf("Booting wince ...\n");                        strcpy(cmd_buf, "wince");            run_command(cmd_buf, 0);        }        else#endif        {            printf("Booting Linux ...\n");                	    run_command (s, 0);        }# else		parse_string_outer(s, FLAG_PARSE_SEMICOLON |				    FLAG_EXIT_FROM_LOOP);# endif# ifdef CONFIG_AUTOBOOT_KEYED		disable_ctrlc(prev);	/* restore Control C checking */# endif	}# ifdef CONFIG_MENUKEY	if (menukey == CONFIG_MENUKEY) {	    s = getenv("menucmd");	    if (s) {# ifndef CFG_HUSH_PARSER		run_command (s, 0);# else		parse_string_outer(s, FLAG_PARSE_SEMICOLON |				    FLAG_EXIT_FROM_LOOP);# endif	    }	}#endif /* CONFIG_MENUKEY */#endif	/* CONFIG_BOOTDELAY */#ifdef CONFIG_AMIGAONEG3SE	{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?