summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile2
-rw-r--r--common/bedbug.c75
-rw-r--r--common/board_f.c3
-rw-r--r--common/cmd_bedbug.c4
-rw-r--r--common/cmd_bootmenu.c517
-rw-r--r--common/cmd_fdc.c117
-rw-r--r--common/cmd_mmc.c14
-rw-r--r--common/cmd_mtdparts.c23
-rw-r--r--common/cmd_nand.c55
-rw-r--r--common/cmd_nvedit.c7
-rw-r--r--common/cmd_pxe.c3
-rw-r--r--common/cmd_scsi.c18
-rw-r--r--common/cmd_sf.c2
-rw-r--r--common/cmd_test.c9
-rw-r--r--common/cmd_ubi.c153
-rw-r--r--common/dlmalloc.c2
-rw-r--r--common/dlmalloc.src2
-rw-r--r--common/env_nand.c3
-rw-r--r--common/env_ubi.c220
-rw-r--r--common/lcd.c143
-rw-r--r--common/menu.c44
21 files changed, 1135 insertions, 281 deletions
diff --git a/common/Makefile b/common/Makefile
index 1abf4ea..0e0fff1 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 60109cf..42ecf61 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 = &bne;
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 29b49c3..7698891 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 9791423..77b6e3e 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 0000000..a3cbffa
--- /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 66e0ef0..dfa3690 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 8c53a10..9f3d6c5 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 5192dee..1c35f9d 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 32348f3..e9d3d3c 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 947d6c4..afa128e 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 ee75db9..2dbd49c 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 266bfa6..13b3d99 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 3f0d414..0a17782 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 d4ec186..acc0ecf 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 35b1d31..5ba4feb 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 2a9d169..3c70d5d 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 32a38bc..d86acff 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 5b69889..b745822 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 0000000..1ed8b02
--- /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 77914ad..edae835 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 6b2a2db..64b461a 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);