diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/Makefile | 2 | ||||
| -rw-r--r-- | common/bedbug.c | 75 | ||||
| -rw-r--r-- | common/board_f.c | 3 | ||||
| -rw-r--r-- | common/cmd_bedbug.c | 4 | ||||
| -rw-r--r-- | common/cmd_bootmenu.c | 517 | ||||
| -rw-r--r-- | common/cmd_fdc.c | 117 | ||||
| -rw-r--r-- | common/cmd_mmc.c | 14 | ||||
| -rw-r--r-- | common/cmd_mtdparts.c | 23 | ||||
| -rw-r--r-- | common/cmd_nand.c | 55 | ||||
| -rw-r--r-- | common/cmd_nvedit.c | 7 | ||||
| -rw-r--r-- | common/cmd_pxe.c | 3 | ||||
| -rw-r--r-- | common/cmd_scsi.c | 18 | ||||
| -rw-r--r-- | common/cmd_sf.c | 2 | ||||
| -rw-r--r-- | common/cmd_test.c | 9 | ||||
| -rw-r--r-- | common/cmd_ubi.c | 153 | ||||
| -rw-r--r-- | common/dlmalloc.c | 2 | ||||
| -rw-r--r-- | common/dlmalloc.src | 2 | ||||
| -rw-r--r-- | common/env_nand.c | 3 | ||||
| -rw-r--r-- | common/env_ubi.c | 220 | ||||
| -rw-r--r-- | common/lcd.c | 143 | ||||
| -rw-r--r-- | common/menu.c | 44 | 
21 files changed, 1135 insertions, 281 deletions
| diff --git a/common/Makefile b/common/Makefile index 1abf4ea79..0e0fff1ff 100644 --- a/common/Makefile +++ b/common/Makefile @@ -66,6 +66,7 @@ COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o  COBJS-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o  COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o  COBJS-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o +COBJS-$(CONFIG_ENV_IS_IN_UBI) += env_ubi.o  COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o  # command @@ -75,6 +76,7 @@ COBJS-$(CONFIG_CMD_SOURCE) += cmd_source.o  COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o  COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o  COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o +COBJS-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o  COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o  COBJS-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o  COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o diff --git a/common/bedbug.c b/common/bedbug.c index 60109cf82..42ecf61ef 100644 --- a/common/bedbug.c +++ b/common/bedbug.c @@ -72,7 +72,7 @@ int downstring __P ((char *));   *			F_INSTR		- output raw instruction.   *			F_LINENO	- show line # info if available.   * - * Returns TRUE if the area was successfully disassembled or FALSE if + * Returns true if the area was successfully disassembled or false if   * a problem was encountered with accessing the memory.   */ @@ -137,8 +137,8 @@ int disppc (unsigned char *memaddr, unsigned char *virtual, int num_instr,  	for (i = 0; i < num_instr; ++i, memaddr += 4, ctx.virtual += 4) {  #ifdef USE_SOURCE_CODE  		if (ctx.flags & F_LINENO) { -			if ((line_info_from_addr ((Elf32_Word) ctx.virtual, filename, -									  funcname, &line_no) == TRUE) && +			if ((line_info_from_addr ((Elf32_Word) ctx.virtual, +				filename, funcname, &line_no) == true) &&  				((line_no != last_line_no) ||  				 (strcmp (last_funcname, funcname) != 0))) {  				print_source_line (filename, funcname, line_no, pfunc); @@ -154,15 +154,15 @@ int disppc (unsigned char *memaddr, unsigned char *virtual, int num_instr,  #ifdef USE_SOURCE_CODE  		if (ctx.flags & F_SYMBOL) {  			if ((symname = -				 symbol_name_from_addr ((Elf32_Word) ctx.virtual, -										TRUE, 0)) != 0) { +				 symbol_name_from_addr((Elf32_Word) ctx.virtual, +						true, 0)) != 0) {  				cursym = symname;  				symoffset = 0;  			} else {  				if ((cursym == 0) &&  					((symname = -					  symbol_name_from_addr ((Elf32_Word) ctx.virtual, -											 FALSE, &symoffset)) != 0)) { +					  symbol_name_from_addr((Elf32_Word) ctx.virtual, +						false, &symoffset)) != 0)) {  					cursym = symname;  				} else {  					symoffset += 4; @@ -205,7 +205,8 @@ int disppc (unsigned char *memaddr, unsigned char *virtual, int num_instr,  		}  		if (((ctx.flags & F_SIMPLE) == 0) || -			(ctx.op->hfunc == 0) || ((*ctx.op->hfunc) (&ctx) == FALSE)) { +			(ctx.op->hfunc == 0) || +			((*ctx.op->hfunc) (&ctx) == false)) {  			sprintf (&ctx.data[ctx.datalen], "%-7s ", ctx.op->name);  			ctx.datalen += 8;  			print_operands (&ctx); @@ -214,7 +215,7 @@ int disppc (unsigned char *memaddr, unsigned char *virtual, int num_instr,  		(*pfunc) (ctx.data);  	} -	return TRUE; +	return true;  }								/* disppc */ @@ -364,10 +365,10 @@ int print_operands (struct ppc_ctx *ctx)   *	value		The address of an unsigned long to be filled in   *			with the value of the operand if it is found.  This   *			will only be filled in if the function returns - *			TRUE.  This may be passed as 0 if the value is + *			true.  This may be passed as 0 if the value is   *			not required.   * - * Returns TRUE if the operand was found or FALSE if it was not. + * Returns true if the operand was found or false if it was not.   */  int get_operand_value (struct opcode *op, unsigned long instr, @@ -379,7 +380,7 @@ int get_operand_value (struct opcode *op, unsigned long instr,    /*------------------------------------------------------------*/  	if (field > n_operands) { -		return FALSE;			/* bad operand ?! */ +		return false;			/* bad operand ?! */  	}  	/* Walk through the operands and list each in order */ @@ -393,10 +394,10 @@ int get_operand_value (struct opcode *op, unsigned long instr,  		if (value) {  			*value = (instr >> opr->shift) & ((1 << opr->bits) - 1);  		} -		return TRUE; +		return true;  	} -	return FALSE; +	return false;  }								/* operand_value */ @@ -649,7 +650,7 @@ int tbr_value (char *name)   * Arguments:   *	ctx		A pointer to the disassembler context record.   * - * Returns TRUE if the simpler form was printed or FALSE if it was not. + * Returns true if the simpler form was printed or false if it was not.   */  int handle_bc (struct ppc_ctx *ctx) @@ -669,33 +670,33 @@ int handle_bc (struct ppc_ctx *ctx)    /*------------------------------------------------------------*/ -	if (get_operand_value (ctx->op, ctx->instr, O_BO, &bo) == FALSE) -		return FALSE; +	if (get_operand_value(ctx->op, ctx->instr, O_BO, &bo) == false) +		return false; -	if (get_operand_value (ctx->op, ctx->instr, O_BI, &bi) == FALSE) -		return FALSE; +	if (get_operand_value(ctx->op, ctx->instr, O_BI, &bi) == false) +		return false;  	if ((bo == 12) && (bi == 0)) {  		ctx->op = &blt;  		sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);  		ctx->datalen += 8;  		print_operands (ctx); -		return TRUE; +		return true;  	} else if ((bo == 4) && (bi == 10)) {  		ctx->op = =⃥  		sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);  		ctx->datalen += 8;  		print_operands (ctx); -		return TRUE; +		return true;  	} else if ((bo == 16) && (bi == 0)) {  		ctx->op = &bdnz;  		sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);  		ctx->datalen += 8;  		print_operands (ctx); -		return TRUE; +		return true;  	} -	return FALSE; +	return false;  }								/* handle_blt */ @@ -719,7 +720,7 @@ int handle_bc (struct ppc_ctx *ctx)   *	pfunc		The address of a function to call to print the output.   *   * - * Returns TRUE if it was able to output the line info, or false if it was + * Returns true if it was able to output the line info, or false if it was   * not.   */ @@ -734,7 +735,7 @@ int print_source_line (char *filename, char *funcname,  	sprintf (out_buf, "%s %s(): line %d", filename, funcname, line_no);  	(*pfunc) (out_buf); -	return TRUE; +	return true;  }								/* print_source_line */ @@ -1039,14 +1040,14 @@ int downstring (char *s)   * Arguments:   *	nextaddr	The address (to be filled in) of the next   *			instruction to execute.  This will only be a valid - *			address if TRUE is returned. + *			address if true is returned.   *   *	step_over	A flag indicating how to compute addresses for   *			branch statements: - *			 TRUE  = Step over the branch (next) - *			 FALSE = step into the branch (step) + *			 true  = Step over the branch (next) + *			 false = step into the branch (step)   * - * Returns TRUE if it was able to compute the address.  Returns FALSE if + * Returns true if it was able to compute the address.  Returns false if   * it has a problem reading the current instruction or one of the registers.   */ @@ -1075,7 +1076,7 @@ int find_next_address (unsigned char *nextaddr, int step_over,  	if (nextaddr == 0 || regs == 0) {  		printf ("find_next_address: bad args"); -		return FALSE; +		return false;  	}  	pc = regs->nip & 0xfffffffc; @@ -1083,7 +1084,7 @@ int find_next_address (unsigned char *nextaddr, int step_over,  	if ((op = find_opcode (instr)) == (struct opcode *) 0) {  		printf ("find_next_address: can't parse opcode 0x%lx", instr); -		return FALSE; +		return false;  	}  	ctr = regs->ctr; @@ -1100,7 +1101,7 @@ int find_next_address (unsigned char *nextaddr, int step_over,  			!get_operand_value (op, instr, O_BI, &bi) ||  			!get_operand_value (op, instr, O_AA, &aa) ||  			!get_operand_value (op, instr, O_LK, &lk)) -			return FALSE; +			return false;  		if ((addr & (1 << 13)) != 0)  			addr = addr - (1 << 14); @@ -1116,7 +1117,7 @@ int find_next_address (unsigned char *nextaddr, int step_over,  		if (!get_operand_value (op, instr, O_LI, &addr) ||  			!get_operand_value (op, instr, O_AA, &aa) ||  			!get_operand_value (op, instr, O_LK, &lk)) -			return FALSE; +			return false;  		if ((addr & (1 << 23)) != 0)  			addr = addr - (1 << 24); @@ -1130,7 +1131,7 @@ int find_next_address (unsigned char *nextaddr, int step_over,  		if (!get_operand_value (op, instr, O_BO, &bo) ||  			!get_operand_value (op, instr, O_BI, &bi) ||  			!get_operand_value (op, instr, O_LK, &lk)) -			return FALSE; +			return false;  		addr = ctr;  		aa = 1; @@ -1143,7 +1144,7 @@ int find_next_address (unsigned char *nextaddr, int step_over,  		if (!get_operand_value (op, instr, O_BO, &bo) ||  			!get_operand_value (op, instr, O_BI, &bi) ||  			!get_operand_value (op, instr, O_LK, &lk)) -			return FALSE; +			return false;  		addr = lr;  		aa = 1; @@ -1227,12 +1228,12 @@ int find_next_address (unsigned char *nextaddr, int step_over,  		step = next = pc + 4;  	} -	if (step_over == TRUE) +	if (step_over == true)  		*(unsigned long *) nextaddr = next;  	else  		*(unsigned long *) nextaddr = step; -	return TRUE; +	return true;  }								/* find_next_address */ diff --git a/common/board_f.c b/common/board_f.c index 29b49c3ab..769889123 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -788,9 +788,6 @@ static init_fnc_t init_sequence_f[] = {  	/* TODO: can we rename this to timer_init()? */  	init_timebase,  #endif -#if defined(CONFIG_BOARD_EARLY_INIT_F) -	board_early_init_f, -#endif  #ifdef CONFIG_ARM  	timer_init,		/* initialize timer */  #endif diff --git a/common/cmd_bedbug.c b/common/cmd_bedbug.c index 979142320..77b6e3e88 100644 --- a/common/cmd_bedbug.c +++ b/common/cmd_bedbug.c @@ -292,7 +292,7 @@ int do_bedbug_step (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		return 1;  	} -	if (!find_next_address ((unsigned char *) &addr, FALSE, bug_ctx.regs)) +	if (!find_next_address((unsigned char *) &addr, false, bug_ctx.regs))  		return 1;  	if (bug_ctx.set) @@ -323,7 +323,7 @@ int do_bedbug_next (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		return 1;  	} -	if (!find_next_address ((unsigned char *) &addr, TRUE, bug_ctx.regs)) +	if (!find_next_address((unsigned char *) &addr, true, bug_ctx.regs))  		return 1;  	if (bug_ctx.set) diff --git a/common/cmd_bootmenu.c b/common/cmd_bootmenu.c new file mode 100644 index 000000000..a3cbffab2 --- /dev/null +++ b/common/cmd_bootmenu.c @@ -0,0 +1,517 @@ +/* + * (C) Copyright 2011-2013 Pali Rohár <pali.rohar@gmail.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 + */ + +#include <common.h> +#include <command.h> +#include <ansi.h> +#include <menu.h> +#include <hush.h> +#include <watchdog.h> +#include <malloc.h> +#include <linux/string.h> + +/* maximum bootmenu entries */ +#define MAX_COUNT	99 + +/* maximal size of bootmenu env + *  9 = strlen("bootmenu_") + *  2 = strlen(MAX_COUNT) + *  1 = NULL term + */ +#define MAX_ENV_SIZE	(9 + 2 + 1) + +struct bootmenu_entry { +	unsigned short int num;		/* unique number 0 .. MAX_COUNT */ +	char key[3];			/* key identifier of number */ +	char *title;			/* title of entry */ +	char *command;			/* hush command of entry */ +	struct bootmenu_data *menu;	/* this bootmenu */ +	struct bootmenu_entry *next;	/* next menu entry (num+1) */ +}; + +struct bootmenu_data { +	int delay;			/* delay for autoboot */ +	int active;			/* active menu entry */ +	int count;			/* total count of menu entries */ +	struct bootmenu_entry *first;	/* first menu entry */ +}; + +enum bootmenu_key { +	KEY_NONE = 0, +	KEY_UP, +	KEY_DOWN, +	KEY_SELECT, +}; + +static char *bootmenu_getoption(unsigned short int n) +{ +	char name[MAX_ENV_SIZE] = "bootmenu_"; + +	if (n > MAX_COUNT) +		return NULL; + +	sprintf(name + 9, "%d", n); +	return getenv(name); +} + +static void bootmenu_print_entry(void *data) +{ +	struct bootmenu_entry *entry = data; +	int reverse = (entry->menu->active == entry->num); + +	/* +	 * Move cursor to line where the entry will be drown (entry->num) +	 * First 3 lines contain bootmenu header + 1 empty line +	 */ +	printf(ANSI_CURSOR_POSITION, entry->num + 4, 1); + +	puts("     "); + +	if (reverse) +		puts(ANSI_COLOR_REVERSE); + +	puts(entry->title); + +	if (reverse) +		puts(ANSI_COLOR_RESET); +} + +static void bootmenu_autoboot_loop(struct bootmenu_data *menu, +				enum bootmenu_key *key, int *esc) +{ +	int i, c; + +	if (menu->delay > 0) { +		printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); +		printf("  Hit any key to stop autoboot: %2d ", menu->delay); +	} + +	while (menu->delay > 0) { +		for (i = 0; i < 100; ++i) { +			if (!tstc()) { +				WATCHDOG_RESET(); +				mdelay(10); +				continue; +			} + +			menu->delay = -1; +			c = getc(); + +			switch (c) { +			case '\e': +				*esc = 1; +				*key = KEY_NONE; +				break; +			case '\r': +				*key = KEY_SELECT; +				break; +			default: +				*key = KEY_NONE; +				break; +			} + +			break; +		} + +		if (menu->delay < 0) +			break; + +		--menu->delay; +		printf("\b\b\b%2d ", menu->delay); +	} + +	printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); +	puts(ANSI_CLEAR_LINE); + +	if (menu->delay == 0) +		*key = KEY_SELECT; +} + +static void bootmenu_loop(struct bootmenu_data *menu, +		enum bootmenu_key *key, int *esc) +{ +	int c; + +	while (!tstc()) { +		WATCHDOG_RESET(); +		mdelay(10); +	} + +	c = getc(); + +	switch (*esc) { +	case 0: +		/* First char of ANSI escape sequence '\e' */ +		if (c == '\e') { +			*esc = 1; +			*key = KEY_NONE; +		} +		break; +	case 1: +		/* Second char of ANSI '[' */ +		if (c == '[') { +			*esc = 2; +			*key = KEY_NONE; +		} else { +			*esc = 0; +		} +		break; +	case 2: +	case 3: +		/* Third char of ANSI (number '1') - optional */ +		if (*esc == 2 && c == '1') { +			*esc = 3; +			*key = KEY_NONE; +			break; +		} + +		*esc = 0; + +		/* ANSI 'A' - key up was pressed */ +		if (c == 'A') +			*key = KEY_UP; +		/* ANSI 'B' - key down was pressed */ +		else if (c == 'B') +			*key = KEY_DOWN; +		/* other key was pressed */ +		else +			*key = KEY_NONE; + +		break; +	} + +	/* enter key was pressed */ +	if (c == '\r') +		*key = KEY_SELECT; +} + +static char *bootmenu_choice_entry(void *data) +{ +	struct bootmenu_data *menu = data; +	struct bootmenu_entry *iter; +	enum bootmenu_key key = KEY_NONE; +	int esc = 0; +	int i; + +	while (1) { +		if (menu->delay >= 0) { +			/* Autoboot was not stopped */ +			bootmenu_autoboot_loop(menu, &key, &esc); +		} else { +			/* Some key was pressed, so autoboot was stopped */ +			bootmenu_loop(menu, &key, &esc); +		} + +		switch (key) { +		case KEY_UP: +			if (menu->active > 0) +				--menu->active; +			/* no menu key selected, regenerate menu */ +			return NULL; +		case KEY_DOWN: +			if (menu->active < menu->count - 1) +				++menu->active; +			/* no menu key selected, regenerate menu */ +			return NULL; +		case KEY_SELECT: +			iter = menu->first; +			for (i = 0; i < menu->active; ++i) +				iter = iter->next; +			return iter->key; +		default: +			break; +		} +	} + +	/* never happens */ +	debug("bootmenu: this should not happen"); +	return NULL; +} + +static void bootmenu_destroy(struct bootmenu_data *menu) +{ +	struct bootmenu_entry *iter = menu->first; +	struct bootmenu_entry *next; + +	while (iter) { +		next = iter->next; +		free(iter->title); +		free(iter->command); +		free(iter); +		iter = next; +	} +	free(menu); +} + +static struct bootmenu_data *bootmenu_create(int delay) +{ +	unsigned short int i = 0; +	const char *option; +	struct bootmenu_data *menu; +	struct bootmenu_entry *iter = NULL; + +	int len; +	char *sep; +	struct bootmenu_entry *entry; + +	menu = malloc(sizeof(struct bootmenu_data)); +	if (!menu) +		return NULL; + +	menu->delay = delay; +	menu->active = 0; +	menu->first = NULL; + +	while ((option = bootmenu_getoption(i))) { +		sep = strchr(option, '='); +		if (!sep) { +			printf("Invalid bootmenu entry: %s\n", option); +			break; +		} + +		entry = malloc(sizeof(struct bootmenu_entry)); +		if (!entry) +			goto cleanup; + +		len = sep-option; +		entry->title = malloc(len + 1); +		if (!entry->title) { +			free(entry); +			goto cleanup; +		} +		memcpy(entry->title, option, len); +		entry->title[len] = 0; + +		len = strlen(sep + 1); +		entry->command = malloc(len + 1); +		if (!entry->command) { +			free(entry->title); +			free(entry); +			goto cleanup; +		} +		memcpy(entry->command, sep + 1, len); +		entry->command[len] = 0; + +		sprintf(entry->key, "%d", i); + +		entry->num = i; +		entry->menu = menu; +		entry->next = NULL; + +		if (!iter) +			menu->first = entry; +		else +			iter->next = entry; + +		iter = entry; +		++i; + +		if (i == MAX_COUNT - 1) +			break; +	} + +	/* Add U-Boot console entry at the end */ +	if (i <= MAX_COUNT - 1) { +		entry = malloc(sizeof(struct bootmenu_entry)); +		if (!entry) +			goto cleanup; + +		entry->title = strdup("U-Boot console"); +		if (!entry->title) { +			free(entry); +			goto cleanup; +		} + +		entry->command = strdup(""); +		if (!entry->command) { +			free(entry->title); +			free(entry); +			goto cleanup; +		} + +		sprintf(entry->key, "%d", i); + +		entry->num = i; +		entry->menu = menu; +		entry->next = NULL; + +		if (!iter) +			menu->first = entry; +		else +			iter->next = entry; + +		iter = entry; +		++i; +	} + +	menu->count = i; +	return menu; + +cleanup: +	bootmenu_destroy(menu); +	return NULL; +} + +static void bootmenu_show(int delay) +{ +	int init = 0; +	void *choice = NULL; +	char *title = NULL; +	char *command = NULL; +	struct menu *menu; +	struct bootmenu_data *bootmenu; +	struct bootmenu_entry *iter; +	char *option, *sep; + +	/* If delay is 0 do not create menu, just run first entry */ +	if (delay == 0) { +		option = bootmenu_getoption(0); +		if (!option) { +			puts("bootmenu option 0 was not found\n"); +			return; +		} +		sep = strchr(option, '='); +		if (!sep) { +			puts("bootmenu option 0 is invalid\n"); +			return; +		} +		run_command(sep+1, 0); +		return; +	} + +	bootmenu = bootmenu_create(delay); +	if (!bootmenu) +		return; + +	menu = menu_create(NULL, bootmenu->delay, 1, bootmenu_print_entry, +			   bootmenu_choice_entry, bootmenu); +	if (!menu) { +		bootmenu_destroy(bootmenu); +		return; +	} + +	for (iter = bootmenu->first; iter; iter = iter->next) { +		if (!menu_item_add(menu, iter->key, iter)) +			goto cleanup; +	} + +	/* Default menu entry is always first */ +	menu_default_set(menu, "0"); + +	puts(ANSI_CURSOR_HIDE); +	puts(ANSI_CLEAR_CONSOLE); +	printf(ANSI_CURSOR_POSITION, 1, 1); + +	init = 1; + +	if (menu_get_choice(menu, &choice)) { +		iter = choice; +		title = strdup(iter->title); +		command = strdup(iter->command); +	} + +cleanup: +	menu_destroy(menu); +	bootmenu_destroy(bootmenu); + +	if (init) { +		puts(ANSI_CURSOR_SHOW); +		puts(ANSI_CLEAR_CONSOLE); +		printf(ANSI_CURSOR_POSITION, 1, 1); +	} + +	if (title && command) { +		debug("Starting entry '%s'\n", title); +		free(title); +		run_command(command, 0); +		free(command); +	} + +#ifdef CONFIG_POSTBOOTMENU +	run_command(CONFIG_POSTBOOTMENU, 0); +#endif +} + +void menu_display_statusline(struct menu *m) +{ +	struct bootmenu_entry *entry; +	struct bootmenu_data *menu; + +	if (menu_default_choice(m, (void *)&entry) < 0) +		return; + +	menu = entry->menu; + +	printf(ANSI_CURSOR_POSITION, 1, 1); +	puts(ANSI_CLEAR_LINE); +	printf(ANSI_CURSOR_POSITION, 2, 1); +	puts("  *** U-Boot Boot Menu ***"); +	puts(ANSI_CLEAR_LINE_TO_END); +	printf(ANSI_CURSOR_POSITION, 3, 1); +	puts(ANSI_CLEAR_LINE); + +	/* First 3 lines are bootmenu header + 2 empty lines between entries */ +	printf(ANSI_CURSOR_POSITION, menu->count + 5, 1); +	puts(ANSI_CLEAR_LINE); +	printf(ANSI_CURSOR_POSITION, menu->count + 6, 1); +	puts("  Press UP/DOWN to move, ENTER to select"); +	puts(ANSI_CLEAR_LINE_TO_END); +	printf(ANSI_CURSOR_POSITION, menu->count + 7, 1); +	puts(ANSI_CLEAR_LINE); +} + +#ifdef CONFIG_MENU_SHOW +int menu_show(int bootdelay) +{ +	bootmenu_show(bootdelay); +	return -1; /* -1 - abort boot and run monitor code */ +} +#endif + +int do_bootmenu(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ +	char *delay_str = NULL; +	int delay = 10; + +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) +	delay = CONFIG_BOOTDELAY; +#endif + +	if (argc >= 2) +		delay_str = argv[1]; + +	if (!delay_str) +		delay_str = getenv("bootmenu_delay"); + +	if (delay_str) +		delay = (int)simple_strtol(delay_str, NULL, 10); + +	bootmenu_show(delay); +	return 0; +} + +U_BOOT_CMD( +	bootmenu, 2, 1, do_bootmenu, +	"ANSI terminal bootmenu", +	"[delay]\n" +	"    - show ANSI terminal bootmenu with autoboot delay" +); diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 66e0ef058..dfa36901e 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -39,13 +39,6 @@  #define PRINTF(fmt,args...)  #endif -#ifndef	TRUE -#define TRUE            1 -#endif -#ifndef FALSE -#define FALSE           0 -#endif -  /*#if defined(CONFIG_CMD_DATE) */  /*#include <rtc.h> */  /*#endif */ @@ -214,9 +207,9 @@ int wait_for_fdc_int(void)  		timeout--;  		udelay(10);  		if(timeout==0) /* timeout occured */ -			return FALSE; +			return false;  	} -	return TRUE; +	return true;  }  /* reads a byte from the FIFO of the FDC and checks direction and RQM bit @@ -244,7 +237,7 @@ int fdc_need_more_output(void)  			c=(unsigned char)read_fdc_byte();  			printf("Error: more output: %x\n",c);  	} -	return TRUE; +	return true;  } @@ -260,10 +253,10 @@ int write_fdc_byte(unsigned char val)  		udelay(10);  		fdc_need_more_output();  		if(timeout==0) /* timeout occured */ -			return FALSE; +			return false;  	}  	write_fdc_reg(FDC_FIFO,val); -	return TRUE; +	return true;  }  /* sets up all FDC commands and issues it to the FDC. If @@ -344,9 +337,9 @@ int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  	}  	for(i=0;i<pCMD->cmdlen;i++) {  		/* PRINTF("write cmd%d = 0x%02X\n",i,pCMD->cmd[i]); */ -		if(write_fdc_byte(pCMD->cmd[i])==FALSE) { +		if (write_fdc_byte(pCMD->cmd[i]) == false) {  			PRINTF("Error: timeout while issue cmd%d\n",i); -			return FALSE; +			return false;  		}  	}  	timeout=FDC_TIME_OUT; @@ -355,12 +348,12 @@ int fdc_issue_cmd(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  			timeout--;  			if(timeout==0) {  				PRINTF(" timeout while reading result%d MSR=0x%02X\n",i,read_fdc_reg(FDC_MSR)); -				return FALSE; +				return false;  			}  		}  		pCMD->result[i]=(unsigned char)read_fdc_byte();  	} -	return TRUE; +	return true;  }  /* selects the drive assigned in the cmd structur and @@ -391,9 +384,10 @@ void stop_fdc_drive(FDC_COMMAND_STRUCT *pCMD)  int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  {  	pCMD->cmd[COMMAND]=FDC_CMD_RECALIBRATE; -	if(fdc_issue_cmd(pCMD,pFG)==FALSE) -		return FALSE; -	while(wait_for_fdc_int()!=TRUE); +	if (fdc_issue_cmd(pCMD, pFG) == false) +		return false; +	while (wait_for_fdc_int() != true); +  	pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;  	return(fdc_issue_cmd(pCMD,pFG));  } @@ -403,9 +397,10 @@ int fdc_recalibrate(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  int fdc_seek(FDC_COMMAND_STRUCT *pCMD,FD_GEO_STRUCT *pFG)  {  	pCMD->cmd[COMMAND]=FDC_CMD_SEEK; -	if(fdc_issue_cmd(pCMD,pFG)==FALSE) -		return FALSE; -	while(wait_for_fdc_int()!=TRUE); +	if (fdc_issue_cmd(pCMD, pFG) == false) +		return false; +	while (wait_for_fdc_int() != true); +  	pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT;  	return(fdc_issue_cmd(pCMD,pFG));  } @@ -421,7 +416,7 @@ int fdc_terminate(FDC_COMMAND_STRUCT *pCMD)  	for(i=0;i<7;i++) {  		pCMD->result[i]=(unsigned char)read_fdc_byte();  	} -	return TRUE; +	return true;  }  /* reads data from FDC, seek commands are issued automatic */ @@ -440,18 +435,18 @@ int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT  	retriesrw=0;  	retriescal=0;  	offset=0; -	if(fdc_seek(pCMD,pFG)==FALSE) { +	if (fdc_seek(pCMD, pFG) == false) {  		stop_fdc_drive(pCMD);  		if (flags)  			enable_interrupts(); -		return FALSE; +		return false;  	}  	if((pCMD->result[STATUS_0]&0x20)!=0x20) {  		printf("Seek error Status: %02X\n",pCMD->result[STATUS_0]);  		stop_fdc_drive(pCMD);  		if (flags)  			enable_interrupts(); -		return FALSE; +		return false;  	}  	/* now determine the next seek point */  	/*	lastblk=pCMD->blnr + blocks; */ @@ -466,11 +461,11 @@ int fdc_read_data(unsigned char *buffer, unsigned long blocks,FDC_COMMAND_STRUCT  retryrw:  		len=sect_size * readblk;  		pCMD->cmd[COMMAND]=FDC_CMD_READ; -		if(fdc_issue_cmd(pCMD,pFG)==FALSE) { +		if (fdc_issue_cmd(pCMD, pFG) == false) {  			stop_fdc_drive(pCMD);  			if (flags)  				enable_interrupts(); -			return FALSE; +			return false;  		}  		for (i=0;i<len;i++) {  			timeout=FDC_TIME_OUT; @@ -492,15 +487,15 @@ retryrw:  							stop_fdc_drive(pCMD);  							if (flags)  								enable_interrupts(); -							return FALSE; +							return false;  						}  						else {  							PRINTF(" trying to recalibrate Try %d\n",retriescal); -							if(fdc_recalibrate(pCMD,pFG)==FALSE) { +							if (fdc_recalibrate(pCMD, pFG) == false) {  								stop_fdc_drive(pCMD);  								if (flags)  									enable_interrupts(); -								return FALSE; +								return false;  							}  							retriesrw=0;  							goto retrycal; @@ -512,7 +507,7 @@ retryrw:  					} /* else >FDC_RW_RETRIES */  				}/* if output */  				timeout--; -			}while(TRUE); +			} while (true);  		} /* for len */  		/* the last sector of a track or all data has been read,  		 * we need to get the results */ @@ -530,22 +525,22 @@ retryrw:  			readblk=blocks;  retrycal:  		/* a seek is necessary */ -		if(fdc_seek(pCMD,pFG)==FALSE) { +		if (fdc_seek(pCMD, pFG) == false) {  			stop_fdc_drive(pCMD);  			if (flags)  				enable_interrupts(); -			return FALSE; +			return false;  		}  		if((pCMD->result[STATUS_0]&0x20)!=0x20) {  			PRINTF("Seek error Status: %02X\n",pCMD->result[STATUS_0]);  			stop_fdc_drive(pCMD); -			return FALSE; +			return false;  		} -	}while(TRUE); /* start over */ +	} while (true); /* start over */  	stop_fdc_drive(pCMD); /* switch off drive */  	if (flags)  		enable_interrupts(); -	return TRUE; +	return true;  }  /* Scan all drives and check if drive is present and disk is inserted */ @@ -559,20 +554,20 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  		pCMD->drive=drives;  		select_fdc_drive(pCMD);  		pCMD->blnr=0; /* set to the 1st block */ -		if(fdc_recalibrate(pCMD,pFG)==FALSE) +		if (fdc_recalibrate(pCMD, pFG) == false)  			continue;  		if((pCMD->result[STATUS_0]&0x10)==0x10)  			continue;  		/* ok drive connected check for disk */  		state|=(1<<drives);  		pCMD->blnr=pFG->size; /* set to the last block */ -		if(fdc_seek(pCMD,pFG)==FALSE) +		if (fdc_seek(pCMD, pFG) == false)  			continue;  		pCMD->blnr=0; /* set to the 1st block */ -		if(fdc_recalibrate(pCMD,pFG)==FALSE) +		if (fdc_recalibrate(pCMD, pFG) == false)  			continue;  		pCMD->cmd[COMMAND]=FDC_CMD_READ_ID; -		if(fdc_issue_cmd(pCMD,pFG)==FALSE) +		if (fdc_issue_cmd(pCMD, pFG) == false)  			continue;  		state|=(0x10<<drives);  	} @@ -584,7 +579,7 @@ int fdc_check_drive(FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  			((state&(0x10<<i))==(0x10<<i)) ? pFG->name : "");  	}  	pCMD->flags=state; -	return TRUE; +	return true;  } @@ -611,9 +606,9 @@ int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  	write_fdc_reg(FDC_CCR,pFG->rate);  	/* then initialize the DSR */  	write_fdc_reg(FDC_DSR,pFG->rate); -	if(wait_for_fdc_int()==FALSE) { +	if (wait_for_fdc_int() == false) {  			PRINTF("Time Out after writing CCR\n"); -			return FALSE; +			return false;  	}  	/* now issue sense Interrupt and status command  	 * assuming only one drive present (drive 0) */ @@ -621,7 +616,7 @@ int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  	for(i=0;i<4;i++) {  		/* issue sense interrupt for all 4 possible drives */  		pCMD->cmd[COMMAND]=FDC_CMD_SENSE_INT; -		if(fdc_issue_cmd(pCMD,pFG)==FALSE) { +		if (fdc_issue_cmd(pCMD, pFG) == false) {  			PRINTF("Sense Interrupt for drive %d failed\n",i);  		}  	} @@ -629,24 +624,24 @@ int fdc_setup(int drive, FDC_COMMAND_STRUCT *pCMD, FD_GEO_STRUCT *pFG)  	pCMD->drive=drive;  	select_fdc_drive(pCMD);  	pCMD->cmd[COMMAND]=FDC_CMD_CONFIGURE; -	if(fdc_issue_cmd(pCMD,pFG)==FALSE) { +	if (fdc_issue_cmd(pCMD, pFG) == false) {  		PRINTF(" configure timeout\n");  		stop_fdc_drive(pCMD); -		return FALSE; +		return false;  	}  	/* issue specify command */  	pCMD->cmd[COMMAND]=FDC_CMD_SPECIFY; -	if(fdc_issue_cmd(pCMD,pFG)==FALSE) { +	if (fdc_issue_cmd(pCMD, pFG) == false) {  		PRINTF(" specify timeout\n");  		stop_fdc_drive(pCMD); -		return FALSE; +		return false;  	}  	/* then, we clear the reset in the DOR */  	/* fdc_check_drive(pCMD,pFG);	*/  	/*	write_fdc_reg(FDC_DOR,0x04); */ -	return TRUE; +	return true;  }  #if defined(CONFIG_CMD_FDOS) @@ -664,30 +659,30 @@ int fdc_fdos_init (int drive)  	FDC_COMMAND_STRUCT *pCMD = &cmd;  	/* setup FDC and scan for drives  */ -	if(fdc_setup(drive,pCMD,pFG)==FALSE) { +	if (fdc_setup(drive, pCMD, pFG) == false) {  		printf("\n** Error in setup FDC **\n"); -		return FALSE; +		return false;  	} -	if(fdc_check_drive(pCMD,pFG)==FALSE) { +	if (fdc_check_drive(pCMD, pFG) == false) {  		printf("\n** Error in check_drives **\n"); -		return FALSE; +		return false;  	}  	if((pCMD->flags&(1<<drive))==0) {  		/* drive not available */  		printf("\n** Drive %d not available **\n",drive); -		return FALSE; +		return false;  	}  	if((pCMD->flags&(0x10<<drive))==0) {  		/* no disk inserted */  		printf("\n** No disk inserted in drive %d **\n",drive); -		return FALSE; +		return false;  	}  	/* ok, we have a valid source */  	pCMD->drive=drive;  	/* read first block */  	pCMD->blnr=0; -	return TRUE; +	return true;  }  /**************************************************************************  * int fdc_fdos_seek @@ -747,11 +742,11 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		return CMD_RET_USAGE;  	}  	/* setup FDC and scan for drives  */ -	if(fdc_setup(boot_drive,pCMD,pFG)==FALSE) { +	if (fdc_setup(boot_drive, pCMD, pFG) == false) {  		printf("\n** Error in setup FDC **\n");  		return 1;  	} -	if(fdc_check_drive(pCMD,pFG)==FALSE) { +	if (fdc_check_drive(pCMD, pFG) == false) {  		printf("\n** Error in check_drives **\n");  		return 1;  	} @@ -769,7 +764,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	pCMD->drive=boot_drive;  	/* read first block */  	pCMD->blnr=0; -	if(fdc_read_data((unsigned char *)addr,1,pCMD,pFG)==FALSE) { +	if (fdc_read_data((unsigned char *)addr, 1, pCMD, pFG) == false) {  		printf("\nRead error:");  		for(i=0;i<7;i++)  			printf("result%d: 0x%02X\n",i,pCMD->result[i]); @@ -801,7 +796,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		nrofblk++;  	printf("Loading %ld Bytes (%d blocks) at 0x%08lx..\n",imsize,nrofblk,addr);  	pCMD->blnr=0; -	if(fdc_read_data((unsigned char *)addr,nrofblk,pCMD,pFG)==FALSE) { +	if (fdc_read_data((unsigned char *)addr, nrofblk, pCMD, pFG) == false) {  		/* read image block */  		printf("\nRead error:");  		for(i=0;i<7;i++) diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 8c53a1031..9f3d6c575 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -164,8 +164,12 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  	}  	if (strcmp(argv[1], "rescan") == 0) { -		struct mmc *mmc = find_mmc_device(curr_device); +		struct mmc *mmc; +		if (argc != 2) +			return CMD_RET_USAGE; + +		mmc = find_mmc_device(curr_device);  		if (!mmc) {  			printf("no mmc device at slot %x\n", curr_device);  			return 1; @@ -179,8 +183,12 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  			return 0;  	} else if (strncmp(argv[1], "part", 4) == 0) {  		block_dev_desc_t *mmc_dev; -		struct mmc *mmc = find_mmc_device(curr_device); +		struct mmc *mmc; + +		if (argc != 2) +			return CMD_RET_USAGE; +		mmc = find_mmc_device(curr_device);  		if (!mmc) {  			printf("no mmc device at slot %x\n", curr_device);  			return 1; @@ -196,6 +204,8 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		puts("get mmc type error!\n");  		return 1;  	} else if (strcmp(argv[1], "list") == 0) { +		if (argc != 2) +			return CMD_RET_USAGE;  		print_mmc_devices('\n');  		return 0;  	} else if (strcmp(argv[1], "dev") == 0) { diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 5192dee8a..1c35f9dd6 100644 --- a/common/cmd_mtdparts.c +++ b/common/cmd_mtdparts.c @@ -106,6 +106,8 @@  #include <onenand_uboot.h>  #endif +DECLARE_GLOBAL_DATA_PTR; +  /* special size referring to all the remaining space in a partition */  #define SIZE_REMAINING		0xFFFFFFFF @@ -1537,6 +1539,7 @@ static int parse_mtdparts(const char *const mtdparts)  	const char *p = mtdparts;  	struct mtd_device *dev;  	int err = 1; +	char tmp_parts[MTDPARTS_MAXLEN];  	debug("\n---parse_mtdparts---\nmtdparts = %s\n\n", p); @@ -1547,7 +1550,12 @@ static int parse_mtdparts(const char *const mtdparts)  	}  	/* re-read 'mtdparts' variable, mtd_devices_init may be updating env */ -	p = getenv("mtdparts"); +	if (gd->flags & GD_FLG_ENV_READY) { +		p = getenv("mtdparts"); +	} else { +		p = tmp_parts; +		getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN); +	}  	if (strncmp(p, "mtdparts=", 9) != 0) {  		printf("mtdparts variable doesn't start with 'mtdparts='\n"); @@ -1705,6 +1713,7 @@ int mtdparts_init(void)  	const char *current_partition;  	int ids_changed;  	char tmp_ep[PARTITION_MAXLEN]; +	char tmp_parts[MTDPARTS_MAXLEN];  	debug("\n---mtdparts_init---\n");  	if (!initialized) { @@ -1718,7 +1727,17 @@ int mtdparts_init(void)  	/* get variables */  	ids = getenv("mtdids"); -	parts = getenv("mtdparts"); +	/* +	 * The mtdparts variable tends to be long. If we need to access it +	 * before the env is relocated, then we need to use our own stack +	 * buffer.  gd->env_buf will be too small. +	 */ +	if (gd->flags & GD_FLG_ENV_READY) { +		parts = getenv("mtdparts"); +	} else { +		parts = tmp_parts; +		getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN); +	}  	current_partition = getenv("partition");  	/* save it for later parsing, cannot rely on current partition pointer diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 32348f377..e9d3d3c1b 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -137,7 +137,8 @@ static inline int str2long(const char *p, ulong *num)  	return *p != '\0' && *endptr == '\0';  } -static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size) +static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size, +		loff_t *maxsize)  {  #ifdef CONFIG_CMD_MTDPARTS  	struct mtd_device *dev; @@ -160,6 +161,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)  	*off = part->offset;  	*size = part->size; +	*maxsize = part->size;  	*idx = dev->id->num;  	ret = set_dev(*idx); @@ -173,10 +175,11 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size)  #endif  } -static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize) +static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *size, +		loff_t *maxsize)  {  	if (!str2off(arg, off)) -		return get_part(arg, idx, off, maxsize); +		return get_part(arg, idx, off, size, maxsize);  	if (*off >= nand_info[*idx].size) {  		puts("Offset exceeds device limit\n"); @@ -184,36 +187,35 @@ static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)  	}  	*maxsize = nand_info[*idx].size - *off; +	*size = *maxsize;  	return 0;  }  static int arg_off_size(int argc, char *const argv[], int *idx, -			loff_t *off, loff_t *size) +			loff_t *off, loff_t *size, loff_t *maxsize)  {  	int ret; -	loff_t maxsize = 0;  	if (argc == 0) {  		*off = 0;  		*size = nand_info[*idx].size; +		*maxsize = *size;  		goto print;  	} -	ret = arg_off(argv[0], idx, off, &maxsize); +	ret = arg_off(argv[0], idx, off, size, maxsize);  	if (ret)  		return ret; -	if (argc == 1) { -		*size = maxsize; +	if (argc == 1)  		goto print; -	}  	if (!str2off(argv[1], size)) {  		printf("'%s' is not a number\n", argv[1]);  		return -1;  	} -	if (*size > maxsize) { +	if (*size > *maxsize) {  		puts("Size exceeds partition or device limit\n");  		return -1;  	} @@ -307,7 +309,8 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])  		if (argc < 3)  			goto usage; -		if (arg_off(argv[2], &idx, &addr, &maxsize)) { +		/* We don't care about size, or maxsize. */ +		if (arg_off(argv[2], &idx, &addr, &maxsize, &maxsize)) {  			puts("Offset or partition name expected\n");  			return 1;  		} @@ -426,7 +429,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  {  	int i, ret = 0;  	ulong addr; -	loff_t off, size; +	loff_t off, size, maxsize;  	char *cmd, *s;  	nand_info_t *nand;  #ifdef CONFIG_SYS_NAND_QUIET @@ -551,7 +554,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		printf("\nNAND %s: ", cmd);  		/* skip first two or three arguments, look for offset and size */ -		if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0) +		if (arg_off_size(argc - o, argv + o, &dev, &off, &size, +				 &maxsize) != 0)  			return 1;  		nand = &nand_info[dev]; @@ -619,7 +623,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		if (s && !strcmp(s, ".raw")) {  			raw = 1; -			if (arg_off(argv[3], &dev, &off, &size)) +			if (arg_off(argv[3], &dev, &off, &size, &maxsize))  				return 1;  			if (argc > 4 && !str2long(argv[4], &pagecount)) { @@ -635,7 +639,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  			rwsize = pagecount * (nand->writesize + nand->oobsize);  		} else {  			if (arg_off_size(argc - 3, argv + 3, &dev, -						&off, &size) != 0) +						&off, &size, &maxsize) != 0)  				return 1;  			rwsize = size; @@ -645,9 +649,11 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		    !strcmp(s, ".e") || !strcmp(s, ".i")) {  			if (read)  				ret = nand_read_skip_bad(nand, off, &rwsize, +							 NULL, maxsize,  							 (u_char *)addr);  			else  				ret = nand_write_skip_bad(nand, off, &rwsize, +							  NULL, maxsize,  							  (u_char *)addr, 0);  #ifdef CONFIG_CMD_NAND_TRIMFFS  		} else if (!strcmp(s, ".trimffs")) { @@ -655,8 +661,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  				printf("Unknown nand command suffix '%s'\n", s);  				return 1;  			} -			ret = nand_write_skip_bad(nand, off, &rwsize, -						(u_char *)addr, +			ret = nand_write_skip_bad(nand, off, &rwsize, NULL, +						maxsize, (u_char *)addr,  						WITH_DROP_FFS);  #endif  #ifdef CONFIG_CMD_NAND_YAFFS @@ -665,9 +671,9 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  				printf("Unknown nand command suffix '%s'.\n", s);  				return 1;  			} -			ret = nand_write_skip_bad(nand, off, &rwsize, -						(u_char *)addr, -						WITH_INLINE_OOB); +			ret = nand_write_skip_bad(nand, off, &rwsize, NULL, +						maxsize, (u_char *)addr, +						WITH_YAFFS_OOB);  #endif  		} else if (!strcmp(s, ".oob")) {  			/* out-of-band data */ @@ -775,7 +781,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  		if (s && !strcmp(s, ".allexcept"))  			allexcept = 1; -		if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0) +		if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size, +				 &maxsize) < 0)  			return 1;  		if (!nand_unlock(&nand_info[dev], off, size, allexcept)) { @@ -873,7 +880,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,  	printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);  	cnt = nand->writesize; -	r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr); +	r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size, +			(u_char *)addr);  	if (r) {  		puts("** Read error\n");  		bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ); @@ -905,7 +913,8 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,  	}  	bootstage_mark(BOOTSTAGE_ID_NAND_TYPE); -	r = nand_read_skip_bad(nand, offset, &cnt, (u_char *) addr); +	r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size, +			(u_char *)addr);  	if (r) {  		puts("** Read error\n");  		bootstage_error(BOOTSTAGE_ID_NAND_READ); diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 947d6c4ed..afa128ece 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -62,9 +62,10 @@ DECLARE_GLOBAL_DATA_PTR;  	!defined(CONFIG_ENV_IS_IN_ONENAND)	&& \  	!defined(CONFIG_ENV_IS_IN_SPI_FLASH)	&& \  	!defined(CONFIG_ENV_IS_IN_REMOTE)	&& \ +	!defined(CONFIG_ENV_IS_IN_UBI)		&& \  	!defined(CONFIG_ENV_IS_NOWHERE)  # error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\ -SPI_FLASH|NVRAM|MMC|FAT|REMOTE} or CONFIG_ENV_IS_NOWHERE +SPI_FLASH|NVRAM|MMC|FAT|REMOTE|UBI} or CONFIG_ENV_IS_NOWHERE  #endif  /* @@ -273,6 +274,10 @@ int setenv(const char *varname, const char *varvalue)  {  	const char * const argv[4] = { "setenv", varname, varvalue, NULL }; +	/* before import into hashtable */ +	if (!(gd->flags & GD_FLG_ENV_READY)) +		return 1; +  	if (varvalue == NULL || varvalue[0] == '\0')  		return _do_env_set(0, 2, (char * const *)argv);  	else diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index ee75db968..2dbd49cbd 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -1280,7 +1280,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)  	/*  	 * Create a menu and add items for all the labels.  	 */ -	m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print); +	m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print, +			NULL, NULL);  	if (!m)  		return NULL; diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 266bfa690..13b3d996f 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -110,7 +110,7 @@ void scsi_scan(int mode)  		scsi_dev_desc[i].vendor[0]=0;  		scsi_dev_desc[i].product[0]=0;  		scsi_dev_desc[i].revision[0]=0; -		scsi_dev_desc[i].removable=FALSE; +		scsi_dev_desc[i].removable = false;  		scsi_dev_desc[i].if_type=IF_TYPE_SCSI;  		scsi_dev_desc[i].dev=i;  		scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN; @@ -125,7 +125,7 @@ void scsi_scan(int mode)  			pccb->pdata=(unsigned char *)&tempbuff;  			pccb->datalen=512;  			scsi_setup_inquiry(pccb); -			if(scsi_exec(pccb)!=TRUE) { +			if (scsi_exec(pccb) != true) {  				if(pccb->contr_stat==SCSI_SEL_TIME_OUT) {  					debug ("Selection timeout ID %d\n",pccb->target);  					continue; /* selection timeout => assuming no device present */ @@ -139,7 +139,7 @@ void scsi_scan(int mode)  				continue; /* skip unknown devices */  			}  			if((modi&0x80)==0x80) /* drive is removable */ -				scsi_dev_desc[scsi_max_devs].removable=TRUE; +				scsi_dev_desc[scsi_max_devs].removable=true;  			/* get info for this device */  			scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0],  				       &tempbuff[8], 8); @@ -152,8 +152,8 @@ void scsi_scan(int mode)  			pccb->datalen=0;  			scsi_setup_test_unit_ready(pccb); -			if(scsi_exec(pccb)!=TRUE) { -				if(scsi_dev_desc[scsi_max_devs].removable==TRUE) { +			if (scsi_exec(pccb) != true) { +				if (scsi_dev_desc[scsi_max_devs].removable == true) {  					scsi_dev_desc[scsi_max_devs].type=perq;  					goto removable;  				} @@ -404,7 +404,7 @@ static ulong scsi_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)  		debug("scsi_read_ext: startblk " LBAF  		      ", blccnt %x buffer %lx\n",  		      start, smallblks, buf_addr); -		if(scsi_exec(pccb)!=TRUE) { +		if (scsi_exec(pccb) != true) {  			scsi_print_error(pccb);  			blkcnt-=blks;  			break; @@ -458,7 +458,7 @@ static ulong scsi_write(int device, ulong blknr,  		}  		debug("%s: startblk " LBAF ", blccnt %x buffer %lx\n",  		      __func__, start, smallblks, buf_addr); -		if (scsi_exec(pccb) != TRUE) { +		if (scsi_exec(pccb) != true) {  			scsi_print_error(pccb);  			blkcnt -= blks;  			break; @@ -521,7 +521,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)  	pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */  	pccb->datalen = 8; -	if (scsi_exec(pccb) != TRUE) +	if (scsi_exec(pccb) != true)  		return 1;  	*capacity = ((lbaint_t)pccb->pdata[0] << 24) | @@ -547,7 +547,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz)  	pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */  	pccb->datalen = 16; -	if (scsi_exec(pccb) != TRUE) +	if (scsi_exec(pccb) != true)  		return 1;  	*capacity = ((uint64_t)pccb->pdata[0] << 56) | diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 3f0d41495..0a17782d6 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -5,8 +5,8 @@   * Licensed under the GPL-2 or later.   */ -#include <div64.h>  #include <common.h> +#include <div64.h>  #include <malloc.h>  #include <spi_flash.h> diff --git a/common/cmd_test.c b/common/cmd_test.c index d4ec18672..acc0ecf99 100644 --- a/common/cmd_test.c +++ b/common/cmd_test.c @@ -21,6 +21,15 @@   * MA 02111-1307 USA   */ +/* + * Define _STDBOOL_H here to avoid macro expansion of true and false. + * If the future code requires macro true or false, remove this define + * and undef true and false before U_BOOT_CMD. This define and comment + * shall be removed if change to U_BOOT_CMD is made to take string + * instead of stringifying it. + */ +#define _STDBOOL_H +  #include <common.h>  #include <command.h> diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c index 35b1d31f9..5ba4feb48 100644 --- a/common/cmd_ubi.c +++ b/common/cmd_ubi.c @@ -23,6 +23,9 @@  #include <asm/errno.h>  #include <jffs2/load_kernel.h> +#undef ubi_msg +#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__) +  #define DEV_TYPE_NONE		0  #define DEV_TYPE_NAND		1  #define DEV_TYPE_ONENAND	2 @@ -263,7 +266,7 @@ out_err:  	return err;  } -static int ubi_volume_write(char *volume, void *buf, size_t size) +int ubi_volume_write(char *volume, void *buf, size_t size)  {  	int err = 1;  	int rsvd_bytes = 0; @@ -308,12 +311,10 @@ static int ubi_volume_write(char *volume, void *buf, size_t size)  		ubi_gluebi_updated(vol);  	} -	printf("%d bytes written to volume %s\n", size, volume); -  	return 0;  } -static int ubi_volume_read(char *volume, char *buf, size_t size) +int ubi_volume_read(char *volume, char *buf, size_t size)  {  	int err, lnum, off, len, tbuf_size;  	void *tbuf; @@ -325,8 +326,6 @@ static int ubi_volume_read(char *volume, char *buf, size_t size)  	if (vol == NULL)  		return ENODEV; -	printf("Read %d bytes from volume %s to %p\n", size, volume, buf); -  	if (vol->updating) {  		printf("updating");  		return EBUSY; @@ -431,26 +430,82 @@ static int ubi_dev_scan(struct mtd_info *info, char *ubidev,  	return 0;  } -static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +int ubi_part(char *part_name, const char *vid_header_offset)  { -	size_t size = 0; -	ulong addr = 0;  	int err = 0; - -	if (argc < 2) -		return CMD_RET_USAGE; +	char mtd_dev[16]; +	struct mtd_device *dev; +	struct part_info *part; +	u8 pnum;  	if (mtdparts_init() != 0) {  		printf("Error initializing mtdparts!\n");  		return 1;  	} +#ifdef CONFIG_CMD_UBIFS +	/* +	 * Automatically unmount UBIFS partition when user +	 * changes the UBI device. Otherwise the following +	 * UBIFS commands will crash. +	 */ +	if (ubifs_is_mounted()) +		cmd_ubifs_umount(); +#endif + +	/* todo: get dev number for NAND... */ +	ubi_dev.nr = 0; + +	/* +	 * Call ubi_exit() before re-initializing the UBI subsystem +	 */ +	if (ubi_initialized) { +		ubi_exit(); +		del_mtd_partitions(ubi_dev.mtd_info); +	} + +	/* +	 * Search the mtd device number where this partition +	 * is located +	 */ +	if (find_dev_and_part(part_name, &dev, &pnum, &part)) { +		printf("Partition %s not found!\n", part_name); +		return 1; +	} +	sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); +	ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); +	if (IS_ERR(ubi_dev.mtd_info)) { +		printf("Partition %s not found on device %s!\n", part_name, +		       mtd_dev); +		return 1; +	} + +	ubi_dev.selected = 1; + +	strcpy(ubi_dev.part_name, part_name); +	err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name, +			vid_header_offset); +	if (err) { +		printf("UBI init error %d\n", err); +		ubi_dev.selected = 0; +		return err; +	} + +	ubi = ubi_devices[0]; + +	return 0; +} + +static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ +	size_t size = 0; +	ulong addr = 0; + +	if (argc < 2) +		return CMD_RET_USAGE; +  	if (strcmp(argv[1], "part") == 0) { -		char mtd_dev[16]; -		struct mtd_device *dev; -		struct part_info *part;  		const char *vid_header_offset = NULL; -		u8 pnum;  		/* Print current partition */  		if (argc == 2) { @@ -467,58 +522,10 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		if (argc < 3)  			return CMD_RET_USAGE; -#ifdef CONFIG_CMD_UBIFS -		/* -		 * Automatically unmount UBIFS partition when user -		 * changes the UBI device. Otherwise the following -		 * UBIFS commands will crash. -		 */ -		if (ubifs_is_mounted()) -			cmd_ubifs_umount(); -#endif - -		/* todo: get dev number for NAND... */ -		ubi_dev.nr = 0; - -		/* -		 * Call ubi_exit() before re-initializing the UBI subsystem -		 */ -		if (ubi_initialized) { -			ubi_exit(); -			del_mtd_partitions(ubi_dev.mtd_info); -		} - -		/* -		 * Search the mtd device number where this partition -		 * is located -		 */ -		if (find_dev_and_part(argv[2], &dev, &pnum, &part)) { -			printf("Partition %s not found!\n", argv[2]); -			return 1; -		} -		sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num); -		ubi_dev.mtd_info = get_mtd_device_nm(mtd_dev); -		if (IS_ERR(ubi_dev.mtd_info)) { -			printf("Partition %s not found on device %s!\n", argv[2], mtd_dev); -			return 1; -		} - -		ubi_dev.selected = 1; -  		if (argc > 3)  			vid_header_offset = argv[3]; -		strcpy(ubi_dev.part_name, argv[2]); -		err = ubi_dev_scan(ubi_dev.mtd_info, ubi_dev.part_name, -				vid_header_offset); -		if (err) { -			printf("UBI init error %d\n", err); -			ubi_dev.selected = 0; -			return err; -		} - -		ubi = ubi_devices[0]; -		return 0; +		return ubi_part(argv[2], vid_header_offset);  	}  	if ((strcmp(argv[1], "part") != 0) && (!ubi_dev.selected)) { @@ -571,6 +578,8 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  	}  	if (strncmp(argv[1], "write", 5) == 0) { +		int ret; +  		if (argc < 5) {  			printf("Please see usage\n");  			return 1; @@ -579,7 +588,13 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  		addr = simple_strtoul(argv[2], NULL, 16);  		size = simple_strtoul(argv[4], NULL, 16); -		return ubi_volume_write(argv[3], (void *)addr, size); +		ret = ubi_volume_write(argv[3], (void *)addr, size); +		if (!ret) { +			printf("%d bytes written to volume %s\n", size, +			       argv[3]); +		} + +		return ret;  	}  	if (strncmp(argv[1], "read", 4) == 0) { @@ -597,8 +612,12 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])  			argc--;  		} -		if (argc == 3) +		if (argc == 3) { +			printf("Read %d bytes from volume %s to %lx\n", size, +			       argv[3], addr); +  			return ubi_volume_read(argv[3], (char *)addr, size); +		}  	}  	printf("Please see usage\n"); diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 2a9d169f9..3c70d5ded 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -201,7 +201,7 @@    MORECORE_FAILURE          (default: -1)       The value returned upon failure of MORECORE.    MORECORE_CLEARS           (default 1) -     True (1) if the routine mapped to MORECORE zeroes out memory (which +     true (1) if the routine mapped to MORECORE zeroes out memory (which       holds for sbrk).    DEFAULT_TRIM_THRESHOLD    DEFAULT_TOP_PAD diff --git a/common/dlmalloc.src b/common/dlmalloc.src index 32a38bc70..d86acffde 100644 --- a/common/dlmalloc.src +++ b/common/dlmalloc.src @@ -198,7 +198,7 @@    MORECORE_FAILURE          (default: -1)       The value returned upon failure of MORECORE.    MORECORE_CLEARS           (default 1) -     True (1) if the routine mapped to MORECORE zeroes out memory (which +     true (1) if the routine mapped to MORECORE zeroes out memory (which       holds for sbrk).    DEFAULT_TRIM_THRESHOLD    DEFAULT_TOP_PAD diff --git a/common/env_nand.c b/common/env_nand.c index 5b69889c0..b745822be 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -281,7 +281,8 @@ int readenv(size_t offset, u_char *buf)  		} else {  			char_ptr = &buf[amount_loaded];  			if (nand_read_skip_bad(&nand_info[0], offset, -					       &len, char_ptr)) +					       &len, NULL, +					       nand_info[0].size, char_ptr))  				return 1;  			offset += blocksize; diff --git a/common/env_ubi.c b/common/env_ubi.c new file mode 100644 index 000000000..1ed8b02e8 --- /dev/null +++ b/common/env_ubi.c @@ -0,0 +1,220 @@ +/* + * (c) Copyright 2012 by National Instruments, + *        Joe Hershberger <joe.hershberger@ni.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 + */ + +#include <common.h> + +#include <command.h> +#include <environment.h> +#include <errno.h> +#include <malloc.h> +#include <search.h> +#include <ubi_uboot.h> +#undef crc32 + +char *env_name_spec = "UBI"; + +env_t *env_ptr; + +DECLARE_GLOBAL_DATA_PTR; + +int env_init(void) +{ +	/* use default */ +	gd->env_addr = (ulong)&default_environment[0]; +	gd->env_valid = 1; + +	return 0; +} + +#ifdef CONFIG_CMD_SAVEENV +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT +static unsigned char env_flags; + +int saveenv(void) +{ +	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); +	ssize_t	len; +	char *res; + +	res = (char *)&env_new->data; +	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); +	if (len < 0) { +		error("Cannot export environment: errno = %d\n", errno); +		return 1; +	} + +	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { +		printf("\n** Cannot find mtd partition \"%s\"\n", +		       CONFIG_ENV_UBI_PART); +		return 1; +	} + +	env_new->crc = crc32(0, env_new->data, ENV_SIZE); +	env_new->flags = ++env_flags; /* increase the serial */ + +	if (gd->env_valid == 1) { +		puts("Writing to redundant UBI... "); +		if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, +				     (void *)env_new, CONFIG_ENV_SIZE)) { +			printf("\n** Unable to write env to %s:%s **\n", +			       CONFIG_ENV_UBI_PART, +			       CONFIG_ENV_UBI_VOLUME_REDUND); +			return 1; +		} +	} else { +		puts("Writing to UBI... "); +		if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, +				     (void *)env_new, CONFIG_ENV_SIZE)) { +			printf("\n** Unable to write env to %s:%s **\n", +			       CONFIG_ENV_UBI_PART, +			       CONFIG_ENV_UBI_VOLUME); +			return 1; +		} +	} + +	puts("done\n"); + +	gd->env_valid = gd->env_valid == 2 ? 1 : 2; + +	return 0; +} +#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ +int saveenv(void) +{ +	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); +	ssize_t	len; +	char *res; + +	res = (char *)&env_new->data; +	len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); +	if (len < 0) { +		error("Cannot export environment: errno = %d\n", errno); +		return 1; +	} + +	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { +		printf("\n** Cannot find mtd partition \"%s\"\n", +		       CONFIG_ENV_UBI_PART); +		return 1; +	} + +	env_new->crc = crc32(0, env_new->data, ENV_SIZE); + +	if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, +			     CONFIG_ENV_SIZE)) { +		printf("\n** Unable to write env to %s:%s **\n", +		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); +		return 1; +	} + +	puts("done\n"); +	return 0; +} +#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ +#endif /* CONFIG_CMD_SAVEENV */ + +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT +void env_relocate_spec(void) +{ +	ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE); +	ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE); +	int crc1_ok = 0, crc2_ok = 0; +	env_t *ep, *tmp_env1, *tmp_env2; + +	tmp_env1 = (env_t *)env1_buf; +	tmp_env2 = (env_t *)env2_buf; + +	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { +		printf("\n** Cannot find mtd partition \"%s\"\n", +		       CONFIG_ENV_UBI_PART); +		set_default_env(NULL); +		return; +	} + +	if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1, +			    CONFIG_ENV_SIZE)) { +		printf("\n** Unable to read env from %s:%s **\n", +		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); +	} + +	if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND, (void *)tmp_env2, +			    CONFIG_ENV_SIZE)) { +		printf("\n** Unable to read redundant env from %s:%s **\n", +		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); +	} + +	crc1_ok = crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc; +	crc2_ok = crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc; + +	if (!crc1_ok && !crc2_ok) { +		set_default_env("!bad CRC"); +		return; +	} else if (crc1_ok && !crc2_ok) { +		gd->env_valid = 1; +	} else if (!crc1_ok && crc2_ok) { +		gd->env_valid = 2; +	} else { +		/* both ok - check serial */ +		if (tmp_env1->flags == 255 && tmp_env2->flags == 0) +			gd->env_valid = 2; +		else if (tmp_env2->flags == 255 && tmp_env1->flags == 0) +			gd->env_valid = 1; +		else if (tmp_env1->flags > tmp_env2->flags) +			gd->env_valid = 1; +		else if (tmp_env2->flags > tmp_env1->flags) +			gd->env_valid = 2; +		else /* flags are equal - almost impossible */ +			gd->env_valid = 1; +	} + +	if (gd->env_valid == 1) +		ep = tmp_env1; +	else +		ep = tmp_env2; + +	env_flags = ep->flags; +	env_import((char *)ep, 0); +} +#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */ +void env_relocate_spec(void) +{ +	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); + +	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) { +		printf("\n** Cannot find mtd partition \"%s\"\n", +		       CONFIG_ENV_UBI_PART); +		set_default_env(NULL); +		return; +	} + +	if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)&buf, +			    CONFIG_ENV_SIZE)) { +		printf("\n** Unable to read env from %s:%s **\n", +		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); +		set_default_env(NULL); +		return; +	} + +	env_import(buf, 1); +} +#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ diff --git a/common/lcd.c b/common/lcd.c index 77914adbc..edae835fb 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -83,9 +83,35 @@  #define CONFIG_CONSOLE_SCROLL_LINES 1  #endif -DECLARE_GLOBAL_DATA_PTR; +/************************************************************************/ +/* ** CONSOLE DEFINITIONS & FUNCTIONS					*/ +/************************************************************************/ +#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) +# define CONSOLE_ROWS		((panel_info.vl_row-BMP_LOGO_HEIGHT) \ +					/ VIDEO_FONT_HEIGHT) +#else +# define CONSOLE_ROWS		(panel_info.vl_row / VIDEO_FONT_HEIGHT) +#endif -ulong lcd_setmem (ulong addr); +#define CONSOLE_COLS		(panel_info.vl_col / VIDEO_FONT_WIDTH) +#define CONSOLE_ROW_SIZE	(VIDEO_FONT_HEIGHT * lcd_line_length) +#define CONSOLE_ROW_FIRST	lcd_console_address +#define CONSOLE_ROW_SECOND	(lcd_console_address + CONSOLE_ROW_SIZE) +#define CONSOLE_ROW_LAST	(lcd_console_address + CONSOLE_SIZE \ +					- CONSOLE_ROW_SIZE) +#define CONSOLE_SIZE		(CONSOLE_ROW_SIZE * CONSOLE_ROWS) +#define CONSOLE_SCROLL_SIZE	(CONSOLE_SIZE - CONSOLE_ROW_SIZE) + +#if LCD_BPP == LCD_MONOCHROME +# define COLOR_MASK(c)		((c)	  | (c) << 1 | (c) << 2 | (c) << 3 | \ +				 (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7) +#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) +# define COLOR_MASK(c)		(c) +#else +# error Unsupported LCD BPP. +#endif + +DECLARE_GLOBAL_DATA_PTR;  static void lcd_drawchars(ushort x, ushort y, uchar *str, int count);  static inline void lcd_puts_xy(ushort x, ushort y, uchar *s); @@ -93,22 +119,25 @@ static inline void lcd_putc_xy(ushort x, ushort y, uchar  c);  static int lcd_init(void *lcdbase); -static void *lcd_logo (void); +static void *lcd_logo(void);  static int lcd_getbgcolor(void);  static void lcd_setfgcolor(int color);  static void lcd_setbgcolor(int color); +static int lcd_color_fg; +static int lcd_color_bg; +int lcd_line_length; +  char lcd_is_enabled = 0; -static char lcd_flush_dcache;	/* 1 to flush dcache after each lcd update */ +static short console_col; +static short console_row; +static void *lcd_console_address; +static void *lcd_base;			/* Start of framebuffer memory	*/ -#ifdef	NOT_USED_SO_FAR -static void lcd_getcolreg(ushort regno, -				ushort *red, ushort *green, ushort *blue); -static int lcd_getfgcolor(void); -#endif	/* NOT_USED_SO_FAR */ +static char lcd_flush_dcache;	/* 1 to flush dcache after each lcd update */  /************************************************************************/ @@ -148,7 +177,7 @@ static void console_scrollup(void)  	/* Clear the last rows */  	memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,  		COLOR_MASK(lcd_color_bg), -	       CONSOLE_ROW_SIZE * rows); +		CONSOLE_ROW_SIZE * rows);  	lcd_sync();  	console_row -= rows; @@ -160,9 +189,8 @@ static inline void console_back(void)  {  	if (--console_col < 0) {  		console_col = CONSOLE_COLS-1 ; -		if (--console_row < 0) { +		if (--console_row < 0)  			console_row = 0; -		}  	}  	lcd_putc_xy(console_col * VIDEO_FONT_WIDTH, @@ -173,16 +201,13 @@ static inline void console_back(void)  static inline void console_newline(void)  { -	++console_row;  	console_col = 0;  	/* Check if we need to scroll the terminal */ -	if (console_row >= CONSOLE_ROWS) { -		/* Scroll everything up */ +	if (++console_row >= CONSOLE_ROWS)  		console_scrollup(); -	} else { +	else  		lcd_sync(); -	}  }  /*----------------------------------------------------------------------*/ @@ -234,9 +259,9 @@ void lcd_puts(const char *s)  		return;  	} -	while (*s) { +	while (*s)  		lcd_putc(*s++); -	} +  	lcd_sync();  } @@ -283,7 +308,7 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)  #endif  #if LCD_BPP == LCD_MONOCHROME -		uchar rest = *d & -(1 << (8-off)); +		uchar rest = *d & -(1 << (8 - off));  		uchar sym;  #endif  		for (i = 0; i < count; ++i) { @@ -313,7 +338,7 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)  #endif  		}  #if LCD_BPP == LCD_MONOCHROME -		*d  = rest | (*d & ((1 << (8-off)) - 1)); +		*d  = rest | (*d & ((1 << (8 - off)) - 1));  #endif  	}  } @@ -340,7 +365,7 @@ static inline void lcd_putc_xy(ushort x, ushort y, uchar c)  #define	N_BLK_VERT	2  #define	N_BLK_HOR	3 -static int test_colors[N_BLK_HOR*N_BLK_VERT] = { +static int test_colors[N_BLK_HOR * N_BLK_VERT] = {  	CONSOLE_COLOR_RED,	CONSOLE_COLOR_GREEN,	CONSOLE_COLOR_YELLOW,  	CONSOLE_COLOR_BLUE,	CONSOLE_COLOR_MAGENTA,	CONSOLE_COLOR_CYAN,  }; @@ -361,7 +386,7 @@ static void test_pattern(void)  	for (v = 0; v < v_max; ++v) {  		uchar iy = v / v_step;  		for (h = 0; h < h_max; ++h) { -			uchar ix = N_BLK_HOR * iy + (h/h_step); +			uchar ix = N_BLK_HOR * iy + h / h_step;  			*pix++ = test_colors[ix];  		}  	} @@ -379,12 +404,12 @@ int lcd_get_size(int *line_length)  	return *line_length * panel_info.vl_row;  } -int drv_lcd_init (void) +int drv_lcd_init(void)  {  	struct stdio_dev lcddev;  	int rc; -	lcd_base = (void *)(gd->fb_base); +	lcd_base = (void *) gd->fb_base;  	lcd_init(lcd_base);		/* LCD initialization */ @@ -397,7 +422,7 @@ int drv_lcd_init (void)  	lcddev.putc  = lcd_putc;		/* 'putc' function */  	lcddev.puts  = lcd_puts;		/* 'puts' function */ -	rc = stdio_register (&lcddev); +	rc = stdio_register(&lcddev);  	return (rc == 0) ? 1 : rc;  } @@ -436,11 +461,11 @@ void lcd_clear(void)  	/* set framebuffer to background color */  	memset((char *)lcd_base,  		COLOR_MASK(lcd_getbgcolor()), -		lcd_line_length*panel_info.vl_row); +		lcd_line_length * panel_info.vl_row);  #endif  	/* Paint the logo and retrieve LCD base address */  	debug("[LCD] Drawing the logo...\n"); -	lcd_console_address = lcd_logo (); +	lcd_console_address = lcd_logo();  	console_col = 0;  	console_row = 0; @@ -468,11 +493,23 @@ static int lcd_init(void *lcdbase)  	debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);  	lcd_ctrl_init(lcdbase); + +	/* +	 * lcd_ctrl_init() of some drivers (i.e. bcm2835 on rpi_b) ignores +	 * the 'lcdbase' argument and uses custom lcd base address +	 * by setting up gd->fb_base. Check for this condition and fixup +	 * 'lcd_base' address. +	 */ +	if ((unsigned long)lcdbase != gd->fb_base) +		lcd_base = (void *)gd->fb_base; + +	debug("[LCD] Using LCD frambuffer at %p\n", lcd_base); +  	lcd_get_size(&lcd_line_length);  	lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;  	lcd_is_enabled = 1;  	lcd_clear(); -	lcd_enable (); +	lcd_enable();  	/* Initialize the console */  	console_col = 0; @@ -513,7 +550,8 @@ ulong lcd_setmem(ulong addr)  	/* Allocate pages for the frame buffer. */  	addr -= size; -	debug("Reserving %ldk for LCD Framebuffer at: %08lx\n", size>>10, addr); +	debug("Reserving %ldk for LCD Framebuffer at: %08lx\n", +	      size >> 10, addr);  	return addr;  } @@ -534,12 +572,10 @@ static void lcd_setbgcolor(int color)  /*----------------------------------------------------------------------*/ -#ifdef	NOT_USED_SO_FAR -static int lcd_getfgcolor(void) +int lcd_getfgcolor(void)  {  	return lcd_color_fg;  } -#endif	/* NOT_USED_SO_FAR */  /*----------------------------------------------------------------------*/ @@ -548,8 +584,6 @@ static int lcd_getbgcolor(void)  	return lcd_color_bg;  } -/*----------------------------------------------------------------------*/ -  /************************************************************************/  /* ** Chipset depending Bitmap / Logo stuff...                          */  /************************************************************************/ @@ -566,13 +600,11 @@ static inline ushort *configuration_get_cmap(void)  	return (ushort *)(panel_info.mmio + ATMEL_LCDC_LUT(0));  #elif !defined(CONFIG_ATMEL_HLCD) && !defined(CONFIG_EXYNOS_FB)  	return panel_info.cmap; -#else -#if defined(CONFIG_LCD_LOGO) +#elif defined(CONFIG_LCD_LOGO)  	return bmp_logo_palette;  #else  	return NULL;  #endif -#endif  }  #ifdef CONFIG_LCD_LOGO @@ -591,15 +623,16 @@ void bitmap_plot(int x, int y)  	immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;  	cpm8xx_t *cp = &(immr->im_cpm);  #endif +	unsigned bpix = NBITS(panel_info.vl_bpix);  	debug("Logo: width %d  height %d  colors %d  cmap %d\n",  		BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,  		ARRAY_SIZE(bmp_logo_palette));  	bmap = &bmp_logo_bitmap[0]; -	fb   = (uchar *)(lcd_base + y * lcd_line_length + x); +	fb   = (uchar *)(lcd_base + y * lcd_line_length + x * bpix / 8); -	if (NBITS(panel_info.vl_bpix) < 12) { +	if (bpix < 12) {  		/* Leave room for default color map  		 * default case: generic system with no cmap (most likely 16bpp)  		 * cmap was set to the source palette, so no change is done. @@ -645,12 +678,12 @@ void bitmap_plot(int x, int y)  		for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {  			memcpy(fb, bmap, BMP_LOGO_WIDTH);  			bmap += BMP_LOGO_WIDTH; -			fb   += panel_info.vl_col; +			fb += panel_info.vl_col;  		}  	}  	else { /* true color mode */  		u16 col16; -		fb16 = (ushort *)(lcd_base + y * lcd_line_length + x); +		fb16 = (ushort *)fb;  		for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {  			for (j = 0; j < BMP_LOGO_WIDTH; j++) {  				col16 = bmp_logo_palette[(bmap[j]-16)]; @@ -736,12 +769,11 @@ static void draw_encoded_bitmap(ushort **fbp, ushort c, int cnt)  		*fb++ = c;  		cnt--;  	} -	(*fbp) = fb; +	*fbp = fb;  }  /* - * Do not call this function directly, must be called from - * lcd_display_bitmap. + * Do not call this function directly, must be called from lcd_display_bitmap.   */  static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb,  				    int x_off, int y_off) @@ -868,8 +900,8 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  	unsigned long pwidth = panel_info.vl_col;  	unsigned colors, bpix, bmp_bpix; -	if (!bmp || !((bmp->header.signature[0] == 'B') && -		(bmp->header.signature[1] == 'M'))) { +	if (!bmp || !(bmp->header.signature[0] == 'B' && +		bmp->header.signature[1] == 'M')) {  		printf("Error: no valid bmp image at %lx\n", bmp_image);  		return 1; @@ -882,7 +914,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  	bpix = NBITS(panel_info.vl_bpix); -	if ((bpix != 1) && (bpix != 8) && (bpix != 16) && (bpix != 32)) { +	if (bpix != 1 && bpix != 8 && bpix != 16 && bpix != 32) {  		printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",  			bpix, bmp_bpix); @@ -950,7 +982,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  	}  #endif -	padded_width = (width&0x3) ? ((width&~0x3)+4) : (width); +	padded_width = (width & 0x3 ? (width & ~0x3) + 4 : width);  #ifdef CONFIG_SPLASH_SCREEN_ALIGN  	splash_align_axis(&x, pwidth, width); @@ -962,7 +994,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  	if ((y + height) > panel_info.vl_row)  		height = panel_info.vl_row - y; -	bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset); +	bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);  	fb   = (uchar *) (lcd_base +  		(y + height - 1) * lcd_line_length + x * bpix / 8); @@ -997,7 +1029,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  				}  			}  			bmap += (padded_width - width); -			fb   -= (byte_width + lcd_line_length); +			fb -= byte_width + lcd_line_length;  		}  		break; @@ -1009,7 +1041,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  				fb_put_word(&fb, &bmap);  			bmap += (padded_width - width) * 2; -			fb   -= (width * 2 + lcd_line_length); +			fb -= width * 2 + lcd_line_length;  		}  		break;  #endif /* CONFIG_BMP_16BPP */ @@ -1023,7 +1055,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y)  				*(fb++) = *(bmap++);  				*(fb++) = *(bmap++);  			} -			fb  -= (lcd_line_length + width * (bpix / 8)); +			fb -= lcd_line_length + width * (bpix / 8);  		}  		break;  #endif /* CONFIG_BMP_32BPP */ @@ -1098,7 +1130,7 @@ static void *lcd_logo(void)  	return (void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length);  #else  	return (void *)lcd_base; -#endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */ +#endif /* CONFIG_LCD_LOGO && !defined(CONFIG_LCD_INFO_BELOW_LOGO) */  }  #ifdef CONFIG_SPLASHIMAGE_GUARD @@ -1150,6 +1182,3 @@ int lcd_get_screen_columns(void)  {  	return CONSOLE_COLS;  } - -/************************************************************************/ -/************************************************************************/ diff --git a/common/menu.c b/common/menu.c index 6b2a2db3e..64b461abb 100644 --- a/common/menu.c +++ b/common/menu.c @@ -47,6 +47,8 @@ struct menu {  	char *title;  	int prompt;  	void (*item_data_print)(void *); +	char *(*item_choice)(void *); +	void *item_choice_data;  	struct list_head items;  }; @@ -174,7 +176,7 @@ static inline struct menu_item *menu_item_by_key(struct menu *m,   * Set *choice to point to the default item's data, if any default item was   * set, and returns 1. If no default item was set, returns -ENOENT.   */ -static inline int menu_default_choice(struct menu *m, void **choice) +int menu_default_choice(struct menu *m, void **choice)  {  	if (m->default_item) {  		*choice = m->default_item->data; @@ -204,18 +206,26 @@ static inline int menu_interactive_choice(struct menu *m, void **choice)  		menu_display(m); -		readret = readline_into_buffer("Enter choice: ", cbuf, -				m->timeout / 10); +		if (!m->item_choice) { +			readret = readline_into_buffer("Enter choice: ", cbuf, +					m->timeout / 10); -		if (readret >= 0) { -			choice_item = menu_item_by_key(m, cbuf); - -			if (!choice_item) { -				printf("%s not found\n", cbuf); -				m->timeout = 0; +			if (readret >= 0) { +				choice_item = menu_item_by_key(m, cbuf); +				if (!choice_item) +					printf("%s not found\n", cbuf); +			} else { +				return menu_default_choice(m, choice);  			} -		} else -			return menu_default_choice(m, choice); +		} else { +			char *key = m->item_choice(m->item_choice_data); + +			if (key) +				choice_item = menu_item_by_key(m, key); +		} + +		if (!choice_item) +			m->timeout = 0;  	}  	*choice = choice_item->data; @@ -348,11 +358,19 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)   * what must be entered to select an item, the item_data_print function should   * make it obvious what the key for each entry is.   * + * item_choice - If not NULL, will be called when asking the user to choose an + * item. Returns a key string corresponding to the choosen item or NULL if + * no item has been selected. + * + * item_choice_data - Will be passed as the argument to the item_choice function + *   * Returns a pointer to the menu if successful, or NULL if there is   * insufficient memory available to create the menu.   */  struct menu *menu_create(char *title, int timeout, int prompt, -				void (*item_data_print)(void *)) +				void (*item_data_print)(void *), +				char *(*item_choice)(void *), +				void *item_choice_data)  {  	struct menu *m; @@ -365,6 +383,8 @@ struct menu *menu_create(char *title, int timeout, int prompt,  	m->prompt = prompt;  	m->timeout = timeout;  	m->item_data_print = item_data_print; +	m->item_choice = item_choice; +	m->item_choice_data = item_choice_data;  	if (title) {  		m->title = strdup(title); |