[U-Boot-Users] [PATCH 1/5] Make autocomplete work with HUSH parser too.

CHANGELOG entry:
Auto complete did not work when the HUSH parser was selected. Fix this obvious problem.
--- Signed-off-by: Pantelis Antoniou pantelis@embeddedalley.com ---
README | 4 ---- common/main.c | 25 +++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/README b/README index f78bf50..0aab04c 100644 --- a/README +++ b/README @@ -1470,10 +1470,6 @@ The following options need to be configured:
Enable auto completion of commands using TAB.
- Note that this feature has NOT been implemented yet - for the "hush" shell. - - CFG_HUSH_PARSER
Define this variable to enable the "hush" shell (from diff --git a/common/main.c b/common/main.c index cc4b50f..a8ae07c 100644 --- a/common/main.c +++ b/common/main.c @@ -718,10 +718,11 @@ static void cread_add_str(char *str, int strsize, int insert, unsigned long *num } }
-static int cread_line(char *buf, unsigned int *len) +static int cread_line(const char *const prompt, char *buf, unsigned int *len) { unsigned long num = 0; unsigned long eol_num = 0; + int num2, col; unsigned long rlen; unsigned long wlen; char ichar; @@ -840,6 +841,7 @@ static int cread_line(char *buf, unsigned int *len) insert = !insert; break; case CTL_CH('x'): + case CTL_CH('u'): /* like that too */ BEGINNING_OF_LINE(); ERASE_TO_EOL(); break; @@ -889,6 +891,25 @@ static int cread_line(char *buf, unsigned int *len) REFRESH_TO_EOL(); continue; } +#ifdef CONFIG_AUTO_COMPLETE + case '\t': + + /* do not autocomplete when in the middle */ + if (num < eol_num) { + getcmd_cbeep(); + break; + } + + buf[num] = '\0'; + col = strlen(prompt) + eol_num; + num2 = num; + if (cmd_auto_complete(prompt, buf, &num2, &col)) { + col = num2 - num; + num += col; + eol_num += col; + } + break; +#endif default: cread_add_char(ichar, insert, &num, &eol_num, buf, *len); break; @@ -931,7 +952,7 @@ int readline (const char *const prompt)
puts (prompt);
- rc = cread_line(p, &len); + rc = cread_line(prompt, p, &len); return rc < 0 ? rc : len; #else char *p = console_buffer;

CHANGELOG entry:
Provide support for RedBoot's FIS & config variables.
For PPC provide also a way to boot a redboot compiled Linux kernel. The bd_t is different in that case.
--- Signed-off-by: Pantelis Antoniou pantelis@embeddedalley.com ---
README | 70 ++++ common/Makefile | 1 common/cmd_bootm.c | 19 + common/redboot.c | 941 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/redboot.h | 91 +++++ 5 files changed, 1121 insertions(+), 1 deletions(-)
diff --git a/README b/README index 0aab04c..502f8ec 100644 --- a/README +++ b/README @@ -2265,6 +2265,76 @@ Low Level (hardware related) configuration options: some other boot loader or by a debugger which performs these intializations itself.
+- CONFIG_REDBOOT + Add support for read-only parsing of the FIS & config areas. + For PPC also add an option to boot a kernel compiled for RedBoot. + + The redboot command is also enabled conditional on CFG_CMD_FLASH. + + - Select a different FIS + > redboot fis select ([bank] [sector] | reset) + + - Display FIS + > redboot fis list + + - Set an environment variable from a member variable of a FIS entry + + > redboot fis setenv var type name + + Where type: flash_base, mem_base, size, entry_point, data_length. + + An example given a FIS entry of + + Name FLASH addr Mem addr Datalen Length Entry point + Linux 0xF0470000 0x00100000 0x000FA000 0x00100000 0x00100000 + + > redboot fis setenv linux_base flash_base Linux + + Would set the environment variable linux_base to 0xf0470000 + + - Print either all the RedBoot config variables or a specific one + + > redboot config printenv [config-var] [member] + + member is one of value, type, enable-sense, enable-key with value + being the default one. + + - Set an environment variable from a RedBoot config variable + + > redboot config setenv var config-var [member] + + For example when given a config variable of + + tsec1_esa=00:08:e5:11:32:33 + type=esa enable-sense=true + + > redboot config setenv ethaddr tsec1_esa + + would set the ethaddr environment variable to 00:08:e5:11:32:33 + + - Boot a RedBoot kernel [PPC specific] + + > redboot exec address + + The PPC bd_t differs for kernels compiled for redboot; this command + lets you boot such a kernel. + + RedBoot config defaults (can be overriden on board config): + + - Sector containing the FIS area (negative values for counting from the end) + CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK -1 + + - FIS directory entry size + CONFIG_REDBOOT_DIRECTORY_ENTRY_SIZE 0x100 + + - Size of the config area + CONFIG_REDBOOT_FLASH_CONFIG_SIZE 4096 + + - Size of the script config variables + CONFIG_REDBOOT_FLASH_SCRIPT_SIZE 256 + + - Size of the string config variables + CONFIG_REDBOOT_FLASH_STRING_SIZE 128
Building the Software: ====================== diff --git a/common/Makefile b/common/Makefile index 8baeab3..b6db7f4 100644 --- a/common/Makefile +++ b/common/Makefile @@ -49,6 +49,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug.o circbuf.o \ flash.o fpga.o ft_build.o \ hush.o kgdb.o lattice.o lattice_ivm_core.o lcd.o lists.o lynxkdi.o \ memsize.o miiphybb.o miiphyutil.o \ + redboot.o \ s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \ usb.o usb_kbd.o usb_storage.o \ virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 7aae8a6..fd02257 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -146,6 +146,12 @@ extern void lynxkdi_boot( image_header_t * ); #define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ #endif
+#ifdef CONFIG_REDBOOT_BD_T_SIZE +extern void board_redboot_bd_t_adapt(void *kbd, + ulong cmd_start, ulong cmd_end, + ulong initrd_start, ulong initrd_end); +#endif + image_header_t header;
ulong load_addr = CFG_LOAD_ADDR; /* Default Load Address */ @@ -533,6 +539,11 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, char *of_flat_tree = NULL; ulong of_data = 0; #endif +#ifdef CONFIG_REDBOOT_BD_T_SIZE +#define BD_T_SIZE max(sizeof(bd_t), CONFIG_REDBOOT_BD_T_SIZE) +#else +#define BD_T_SIZE sizeof(bd_t) +#endif
if ((s = getenv ("initrd_high")) != NULL) { /* a value of "no" or a similar string will act like 0, @@ -575,7 +586,7 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, debug ("=> set upper limit to 0x%08lX\n", sp);
cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); - kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF); + kbd = (bd_t *)(((ulong)cmdline - BD_T_SIZE) & ~0xF);
if ((s = getenv("bootargs")) == NULL) s = ""; @@ -904,6 +915,12 @@ do_bootm_linux (cmd_tbl_t *cmdtp, int flag, initrd_end = 0; }
+ /* redboot bd_t modify */ +#ifdef CONFIG_REDBOOT_BD_T_SIZE + if ((s = getenv ("redboot_bd_t")) != NULL) + board_redboot_bd_t_adapt(kbd, cmd_start, cmd_end, initrd_start, initrd_end); +#endif + debug ("## Transferring control to Linux (at address %08lx) ...\n", (ulong)kernel);
diff --git a/common/redboot.c b/common/redboot.c new file mode 100644 index 0000000..eb19a58 --- /dev/null +++ b/common/redboot.c @@ -0,0 +1,941 @@ +/* + * (C) Copyright 2006 - Embedded Alley Solutions Inc. + * by Pantelis Antoniou, pantelis@embeddedalley.com + * + * Based on Linux & RedBoot code fragments + * by David Woodhouse, dwmw2@infradead.org + * by Mark Sattler, msalter@redhat.com + * by Gary Thomas, gthomas@redhat.com + * + * RedBoot flash images/configuration & kernel startup + * + * 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 <malloc.h> +#include <flash.h> +#include <command.h> + +#include <redboot.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +#else +# define SHOW_BOOT_PROGRESS(arg) +#endif + +#ifdef CFG_INIT_RAM_LOCK +#include <asm/cache.h> +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_FLASH) && defined(CONFIG_REDBOOT) + +DECLARE_GLOBAL_DATA_PTR; + +extern void board_redboot_bd_t_adapt(void *kbd, + ulong cmd_start, ulong cmd_end, + ulong initrd_start, ulong initrd_end); + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +static inline int redboot_checksum(struct fis_image_desc *img) +{ + /* RedBoot doesn't actually write the desc_cksum field yet AFAICT */ + return 1; +} + +static int get_sector_size(flash_info_t *info, int sector) +{ + ulong s, e; + + if (info->flash_id == FLASH_UNKNOWN) + return 0; + + if ((unsigned int)sector >= info->sector_count) + return 0; + + s = info->start[sector]; + if (sector < info->sector_count - 1) + e = info->start[sector + 1]; + else + e = info->start[0] + info->size; + + return e - s; +} + +/* get the sector which corresponds to this address */ +static int get_sector(flash_info_t *info, void *ptr) +{ + int i; + ulong s, e; + + if (info->flash_id == FLASH_UNKNOWN) + return -1; + + if (info->start[0] > (ulong)ptr || + info->start[info->sector_count - 1] < (ulong)ptr) + return -1; + + for (i = 0; i < info->sector_count; i++) { + s = info->start[i]; + if (i < info->sector_count - 1) + e = info->start[i + 1]; + else + e = info->start[0] + info->size; + + if (s <= (ulong)ptr && e > (ulong)ptr) + return i; + } + + /* should not happen */ + return -1; +} + +static void *get_fis(flash_info_t *info, void *fis) +{ + int dir_block, sector; + + if (info->flash_id == FLASH_UNKNOWN) + return NULL; + + /* already given a fis address (verify it) */ + if (fis != NULL) { + if (info->start[0] > (ulong)fis || + info->start[info->sector_count - 1] < (ulong)fis) + return NULL; + return fis; + } + + /* go with defaults */ + dir_block = CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK; + if (dir_block < 0) + sector = info->sector_count + dir_block; + else + sector = dir_block; + + if ((unsigned int)sector >= info->sector_count) + return NULL; + + return (void *)info->start[sector]; +} + +static int get_fis_slots(flash_info_t *info, void *fis, int *swapped) +{ + int i, sector, sector_size, slots; + struct fis_image_desc *ptr; + + *swapped = -1; + + fis = get_fis(info, fis); + if (fis == NULL) + return -1; + + sector = get_sector(info, fis); + sector_size = get_sector_size(info, sector); + + slots = sector_size / sizeof(struct fis_image_desc); + + /* first pass; detect swap status */ + for (i = 0, ptr = fis; i < slots; i++, ptr++) { + if (ptr->name[0] == 0xFF) + break; + + if (!memcmp(ptr->name, "FIS directory", 14)) + *swapped = swab32(ptr->size) == sector_size; + } + + if (*swapped == -1) + return -1; + + return i; +} + +void *redboot_fis_get(int bank, int dir_block, flash_info_t **infop) +{ + flash_info_t *info; + int block; + + if (bank < 1 || bank > CFG_MAX_FLASH_BANKS) { + printf ("Only FLASH Banks # 1 ... # %d supported\n", + CFG_MAX_FLASH_BANKS); + return NULL; + } + info = &flash_info[bank-1]; + if (info->flash_id == FLASH_UNKNOWN) { + printf ("FLASH Bank #%d, not present\n", bank); + return NULL; + } + + if (dir_block < 0) + block = info->sector_count + dir_block; + else + block = dir_block; + + if ((unsigned int)block >= info->sector_count) { + printf ("FLASH dir_block %d out of range in Bank #%d\n", dir_block, bank); + return NULL; + } + + if (infop) + *infop = info; + return (void *)info->start[block]; +} + + +int redboot_fis_entry_lookup(flash_info_t *info, void *fis, struct fis_image_desc *fis_buf, const char *name) +{ + int i, slots, swapped, name_len; + struct fis_image_desc *ptr; + + fis = get_fis(info, fis); + if (fis == NULL) + return -1; + + slots = get_fis_slots(info, fis, &swapped); + if (slots == -1) { + printf("fis list: FIS not found\n"); + return -1; + } + + name_len = strlen(name); + + /* now do the proper read (with swapping if needed */ + for (i = 0, ptr = fis; i < slots; i++, ptr++) { + + if (ptr->name[0] == 0xFF) + break; + + /* copy to buffer */ + memcpy(fis_buf, ptr, sizeof(struct fis_image_desc)); + if (swapped) { + /* The unsigned long fields were written with the + * wrong byte sex, name and pad have no byte sex. + */ + swab32s(&fis_buf->flash_base); + swab32s(&fis_buf->mem_base); + swab32s(&fis_buf->size); + swab32s(&fis_buf->entry_point); + swab32s(&fis_buf->data_length); + swab32s(&fis_buf->desc_cksum); + swab32s(&fis_buf->file_cksum); + } + + /* found */ + if (strcmp(name, fis_buf->name) == 0) + return 0; + } + + return -1; +} + +int redboot_fis_list(flash_info_t *info, void *fis) +{ + int i, slots, swapped, found; + static struct fis_image_desc fis_buf; /* static; to save stack space */ + struct fis_image_desc *ptr; + u32 last, lowest, flash_base; + + fis = get_fis(info, fis); + if (fis == NULL) { + printf("fis list: could not get FIS\n"); + return -1; + } + + slots = get_fis_slots(info, fis, &swapped); + if (slots == -1) { + printf("fis list: FIS not found\n"); + return -1; + } + + printf("%-16s %-10s %-10s %-10s %-10s %-s\n", + "Name", "FLASH addr", "Mem addr", + "Datalen", "Length", "Entry point" ); + + last = 0; + do { + found = -1; + lowest = 0xFFFFFFFF; + + /* now do the proper read (with swapping if needed */ + for (i = 0, ptr = fis; i < slots; i++, ptr++) { + + if (ptr->name[0] == 0xFF) + break; + + if (swapped) + flash_base = swab32(ptr->flash_base); + else + flash_base = ptr->flash_base; + + if (flash_base > last && flash_base < lowest) { + lowest = flash_base; + found = i; + } + } + + if (found >= 0) { + ptr = fis; + memcpy(&fis_buf, &ptr[found], sizeof(struct fis_image_desc)); + if (swapped) { + /* The unsigned long fields were written with the + * wrong byte sex, name and pad have no byte sex. + */ + swab32s(&fis_buf.flash_base); + swab32s(&fis_buf.mem_base); + swab32s(&fis_buf.size); + swab32s(&fis_buf.entry_point); + swab32s(&fis_buf.data_length); + swab32s(&fis_buf.desc_cksum); + swab32s(&fis_buf.file_cksum); + } + + printf("%-16s 0x%08lX 0x%08lX 0x%08lX 0x%08lX 0x%08lX\n", + fis_buf.name, + (unsigned long)fis_buf.flash_base, fis_buf.mem_base, + fis_buf.data_length, fis_buf.size, + (unsigned long)fis_buf.entry_point); + } + last = lowest; + } while (found >= 0); + + return 0; +} + +int redboot_fis_setenv(flash_info_t *info, void *fis, const char *name, const char *what, char *var) +{ + static struct fis_image_desc fis_buf; /* static; to save stack space */ + static char varbuf[12]; + int i; + + i = redboot_fis_entry_lookup(info, fis, &fis_buf, name); + if (i != 0) + return -1; + + if (strcmp(what, "flash_base") == 0) + sprintf(varbuf, "0x%x", fis_buf.flash_base); + else if (strcmp(what, "mem_base") == 0) + sprintf(varbuf, "0x%x", fis_buf.mem_base); + else if (strcmp(what, "size") == 0) + sprintf(varbuf, "0x%x", fis_buf.size); + else if (strcmp(what, "entry_point") == 0) + sprintf(varbuf, "0x%x", fis_buf.entry_point); + else if (strcmp(what, "data_length") == 0) + sprintf(varbuf, "0x%x", fis_buf.data_length); + else + return -1; + + setenv(var, varbuf); + + return 0; +} + +/*************************************************************************/ + +#define CONFIG_KEY1 0x0badface +#define CONFIG_KEY2 0xdeaddead + +// +// Layout of config data +// Each data item is variable length, with the name, type and dependencies +// encoded into the object. +// offset contents +// 0 data type +// 1 length of name (N) +// 2 enable sense +// 3 length of enable key (M) +// 4 key name +// N+4 enable key +// M+N+4 data value +// + +#define TYPE(dp) ((dp)[0]) +#define KEYLEN(dp) ((dp)[1]) +#define ENABLE_SENSE(dp) ((dp)[2]) +#define ENABLE_KEYLEN(dp) ((dp)[3]) +#define KEY(dp) ((dp)+4) +#define ENABLE_KEY(dp) ((dp)+4+KEYLEN(dp)) +#define VALUE(dp) ((dp)+4+KEYLEN(dp)+ENABLE_KEYLEN(dp)) + +void *get_config(flash_info_t *info, void *fis, int *sizep, int *swappedp) +{ + static struct fis_image_desc fis_buf; /* static; to save stack space */ + int i; + ulong base, size; + void *config; + u32 *ps, *pe; + + /* lookup the RedBoot config */ + i = redboot_fis_entry_lookup(info, fis, &fis_buf, "RedBoot config"); + if (i != 0) + return NULL; + + base = fis_buf.flash_base; + size = fis_buf.data_length; + + config = (void *)base; + + /* verify */ + ps = (u32 *)base; + if (ps[1] != CONFIG_KEY1 && ps[1] != swab32(CONFIG_KEY1)) + return NULL; + + if (ps[1] == CONFIG_KEY1) { + *swappedp = 0; + if (ps[0] != size) + return NULL; + pe = (u32 *)(base + ps[0]); + if (pe[-2] != CONFIG_KEY2) + return NULL; + } else { + *swappedp = 1; + if (swab32(ps[0]) != size) + return NULL; + pe = (u32 *)(base + swab32(ps[0])); + if (pe[-2] != swab32(CONFIG_KEY2)) + return NULL; + } + + *sizep = size; + return config; +} + +#define CONFIG_EMPTY 0 +#define CONFIG_BOOL 1 +#define CONFIG_INT 2 +#define CONFIG_STRING 3 +#define CONFIG_SCRIPT 4 +#define CONFIG_IP 5 +#define CONFIG_ESA 6 +#define CONFIG_NETPORT 7 + +static const int config_len_tab[] = { + [CONFIG_EMPTY] = 0, + [CONFIG_BOOL] = 4, + [CONFIG_INT] = 4, + [CONFIG_STRING] = CONFIG_REDBOOT_FLASH_STRING_SIZE, + [CONFIG_SCRIPT] = CONFIG_REDBOOT_FLASH_SCRIPT_SIZE, + [CONFIG_IP] = 4, + [CONFIG_ESA] = 8, + [CONFIG_NETPORT]= CONFIG_REDBOOT_FLASH_STRING_SIZE, +}; + +static const char *config_txt_tab[] = { + [CONFIG_EMPTY] = "", + [CONFIG_BOOL] = "bool", + [CONFIG_INT] = "int", + [CONFIG_STRING] = "string", + [CONFIG_SCRIPT] = "script", + [CONFIG_IP] = "ip", + [CONFIG_ESA] = "esa", + [CONFIG_NETPORT]= "netport", +}; + +static inline int config_length(int type) +{ + if ((unsigned int)type >= sizeof(config_len_tab)/sizeof(config_len_tab[0])) + return -1; + return config_len_tab[type]; +} + +static const char *config_format_value(int type, const char *value, char *small_buf, int swapped) +{ + int val; + unsigned int uval; + const char *fmt; + + switch (type) { + case CONFIG_BOOL: + val = *(int *)value; + if (swapped) + val = swab32(val); + fmt = val ? "true" : "false"; + break; + case CONFIG_INT: + val = *(int *)value; + if (swapped) + val = swab32(val); + sprintf(small_buf, "%d", val); + fmt = small_buf; + break; + case CONFIG_STRING: + fmt = value; + break; + case CONFIG_SCRIPT: + fmt = value; + break; + case CONFIG_IP: + uval = *(unsigned int *)value; + if (swapped) + uval = swab32(uval); + sprintf(small_buf, "%u.%u.%u.%u", + (uval >> 24) & 0xff, (uval >> 16) & 0xff, + (uval >> 8) & 0xff, uval & 0xff); + fmt = small_buf; + break; + case CONFIG_ESA: + sprintf(small_buf, "%02x:%02x:%02x:%02x:%02x:%02x", + value[0] & 0xff, value[1] & 0xff, + value[2] & 0xff, value[3] & 0xff, + value[4] & 0xff, value[5] & 0xff); + fmt = small_buf; + break; + case CONFIG_NETPORT: + fmt = value; + break; + + default: + fmt = ""; /* empty */ + break; + } + + return fmt; +} + +int redboot_config_printenv(flash_info_t *info, void *fis, char *small_buf, const char *what) +{ + int size, cfglen, len, printit, swapped; + void *config; + char *dp, *dpe; + + if (small_buf == NULL) + return -1; + + config = get_config(info, fis, &size, &swapped); + if (config == NULL) + return -1; + + /* point to the config data */ + dp = config + 8; + dpe = config + size - 8; + + for (; dp < dpe; dp += len) { + + cfglen = config_length(TYPE(dp)); + if (cfglen < 0) /* illegal type */ + return -1; + + len = 4 + KEYLEN(dp) + ENABLE_KEYLEN(dp) + cfglen; + + /* don't bother with the empty */ + if (TYPE(dp) == CONFIG_EMPTY) + continue; + + /* printf("%p: %02x %02x %02x %02x\n", + dp, (int)dp[0] & 0xff, (int)dp[1] & 0xff, + (int)dp[2] & 0xff, (int)dp[3] & 0xff); */ + + printit = what == NULL || (what != NULL && strcmp(what, KEY(dp)) == 0); + + if (printit) { + printf("%s=%s\n", KEY(dp), config_format_value(TYPE(dp), VALUE(dp), small_buf, swapped)); + printf("\ttype=%s", config_txt_tab[(int)TYPE(dp)]); + printf(" enable-sense=%s", ENABLE_SENSE(dp) ? "true" : "false"); + if (ENABLE_KEYLEN(dp) > 0) + printf(" enable-key=%s", ENABLE_KEY(dp)); + printf("\n"); + + if (what) + break; + } + } + + return 0; +} + +const char *redboot_config_getenv(flash_info_t *info, void *fis, char *small_buf, const char *what, const char *special) +{ + int size, cfglen, len, swapped; + void *config; + char *dp, *dpe; + + /* this time we need that */ + if (what == NULL || small_buf == NULL) + return NULL; + + config = get_config(info, fis, &size, &swapped); + if (config == NULL) + return NULL; + + /* point to the config data */ + dp = config + 8; + dpe = config + size - 8; + + for (; dp < dpe; dp += len) { + + cfglen = config_length(TYPE(dp)); + if (cfglen < 0) /* illegal type */ + return NULL; + + len = 4 + KEYLEN(dp) + ENABLE_KEYLEN(dp) + cfglen; + + /* don't bother with the empty */ + if (TYPE(dp) == CONFIG_EMPTY) + continue; + + if (strcmp(what, KEY(dp)) == 0) { + + /* return value */ + if (special == NULL || strcmp(special, "value") == 0) + return config_format_value(TYPE(dp), VALUE(dp), small_buf, swapped); + + if (strcmp(special, "type") == 0) + return config_txt_tab[(int)TYPE(dp)]; + + if (strcmp(special, "enable-sense") == 0) + return ENABLE_SENSE(dp) ? "true" : "false"; + + if (strcmp(special, "enable-key") == 0) + return ENABLE_KEY(dp); + } + } + + return NULL; +} + +int redboot_config_setenv(flash_info_t *info, void *fis, + const char *var, const char *what, const char *special) +{ + static char small_buf[18]; + const char *value; + + value = redboot_config_getenv(info, fis, small_buf, what, special); + if (!value) + return -1; + + setenv((char *)var, (char *)value); + + return 0; +} + +/*************************************************************/ + +#ifdef CONFIG_PPC + +/* Note: Only tested on a PPC board - other arches + * should be made to work with not much trouble + * + * The way this works is: we do pretty much what + * we do for a bootm case of a uImage (even creating + * the u-boot's idea of bd_t). And then we call + * board specific code to fix the mess. + */ + +static void __attribute__((noinline)) +redboot_linux_exec(ulong addr, ulong ramdisk_address, ulong ramdisk_length) +{ + ulong sp; + ulong initrd_start, initrd_end; + ulong cmd_start, cmd_end; + char *cmdline; + char *s; + bd_t *kbd; + + initrd_start = ramdisk_address; + initrd_end = ramdisk_address + ramdisk_length; + + /* + * Booting a (Linux) kernel image + * + * Allocate space for command line and board info - the + * address should be as high as possible within the reach of + * the kernel (see CFG_BOOTMAPSZ settings), but in unused + * memory, which means far enough below the current stack + * pointer. + */ + + /* point stack at the end of memory */ + /* redboot is different that u-boot in that regard */ + sp = (gd->bd->bi_memstart + gd->bd->bi_memsize) - 16; + sp &= ~0x0f; + + debug ("## Current stack ends at 0x%08lX ", sp); + + sp -= 2048; /* just to be sure */ + + debug ("=> set upper limit to 0x%08lX\n", sp); + + cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF); + kbd = (bd_t *)(((ulong)cmdline - CONFIG_REDBOOT_BD_T_SIZE) & ~0xF); + + if ((s = getenv("bootargs")) != NULL) { + + strcpy (cmdline, s); + + cmd_start = (ulong)&cmdline[0]; + cmd_end = cmd_start + strlen(cmdline); + } else { + cmd_start = 0; + cmd_end = 0; + } + + *kbd = *(gd->bd); + + if ((s = getenv("clocks_in_mhz")) != NULL) { + /* convert all clock information to MHz */ + kbd->bi_intfreq /= 1000000L; + kbd->bi_busfreq /= 1000000L; +#if defined(CONFIG_MPC8220) + kbd->bi_inpfreq /= 1000000L; + kbd->bi_pcifreq /= 1000000L; + kbd->bi_pevfreq /= 1000000L; + kbd->bi_flbfreq /= 1000000L; + kbd->bi_vcofreq /= 1000000L; +#endif +#if defined(CONFIG_CPM2) + kbd->bi_cpmfreq /= 1000000L; + kbd->bi_brgfreq /= 1000000L; + kbd->bi_sccfreq /= 1000000L; + kbd->bi_vco /= 1000000L; +#endif +#if defined(CONFIG_MPC5xxx) + kbd->bi_ipbfreq /= 1000000L; + kbd->bi_pcifreq /= 1000000L; +#endif /* CONFIG_MPC5xxx */ + } + + /* convert u-boot bd_t to redboot_bd_t in place */ + board_redboot_bd_t_adapt(kbd, cmd_start, cmd_end, initrd_start, initrd_end); + + debug ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong)kernel); + + SHOW_BOOT_PROGRESS (15); + +#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500) + unlock_ram_in_cache(); +#endif + dcache_disable(); + icache_disable(); + disable_interrupts(); + + /* Call into Linux */ + __asm__ volatile ( + /* Start by disabling MMU - the mappings are */ + /* 1-1 so this should not cause any problems */ + "mfmsr 3\n" + "li 4,0xFFFFFFCF\n" + "and 3,3,4\n" + "sync\n" + "mtmsr 3\n" + "sync\n" + + /* Now set up parameters to jump into linux */ + + "mtlr %0\n" /* set entry address in LR */ + "mr 1,%1\n" /* set stack pointer */ + "mr 3,%2\n" /* set board info in R3 */ + "mr 4,%3\n" /* set command line in R4 */ + "blr \n" /* jump into linux */ + : + : "r"(addr), "r"(sp), "r"(kbd), "r"(cmd_start) + : "r3", "r4"); + + /* never reached */ +} +#endif /* CONFIG_PPC */ + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +int do_redboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int i, j; + char *name, *var; + static int bank = 1; + static int dir_block = -1; /* defaults */ + void *fis; + static char small_buf[18]; + const char *value; + + if (argc < 2) + goto usage; + + if (strcmp(argv[1], "fis") == 0) { + + if (argc < 3) + goto usage; + + if (strcmp(argv[2], "select") == 0) { + + i = bank; + j = dir_block; + + if (argc == 3 || strcmp(argv[3], "show") == 0) { + ; /* nothing */ + } else if (argc >= 4 && strcmp(argv[3], "reset") == 0) { + i = 1; + j = -1; + } else { + if (argc >= 4) + i = simple_strtoul(argv[3], NULL, 16); + if (argc >= 5) + j = simple_strtol(argv[4], NULL, 16); + } + + fis = redboot_fis_get(i, j, NULL); + if (fis == NULL) { + printf ("Illegal selection: bank %ld, dir_block # %ld\n", i, j); + return 1; + } + + printf ("bank #%ld, dir-block #%ld: RedBoot FIS @%p\n", bank, dir_block, fis); + bank = i; + dir_block = j; + return 0; + } + + if (strcmp(argv[2], "list") == 0) { + + fis = redboot_fis_get(bank, dir_block, NULL); + if (fis == NULL) { + printf ("Illegal selection: bank %ld, dir_block # %ld\n", bank, dir_block); + return 1; + } + + printf ("\nbank #%ld, dir-block #%ld: RedBoot FIS @%p\n", bank, dir_block, fis); + + redboot_fis_list(&flash_info[bank-1], fis); + + return 0; + } + + if (strcmp(argv[2], "setenv") == 0) { + + if (argc < 6) + goto usage; + + var = argv[3]; + name = argv[5]; + + fis = redboot_fis_get(bank, dir_block, NULL); + if (fis == NULL) { + printf ("Illegal selection: bank %ld, dir_block # %ld\n", bank, dir_block); + return 1; + } + + i = redboot_fis_setenv(&flash_info[bank-1], fis, name, argv[4], var); + if (i != 0) { + printf ("Unable to set var '%s' from '%s'\n", argv[4], name); + return 1; + } + + return 0; + } + } + + if (strcmp(argv[1], "config") == 0) { + + if (argc < 3) + goto usage; + + fis = redboot_fis_get(bank, dir_block, NULL); + if (fis == NULL) { + printf ("Illegal selection: bank %ld, dir_block # %ld\n", bank, dir_block); + return 1; + } + + if (strcmp(argv[2], "printenv") == 0) { + + if (argc >= 5) { + value = redboot_config_getenv(&flash_info[bank-1], fis, small_buf, argv[3], argv[4]); + if (value) + printf("%s=%s\n", argv[3], value); + } else + redboot_config_printenv(&flash_info[bank-1], fis, small_buf, argc >= 4 ? argv[3] : NULL); + + return 0; + } + + if (strcmp(argv[2], "setenv") == 0) { + + if (argc < 5) + goto usage; + + i = redboot_config_setenv(&flash_info[bank-1], fis, + argv[3], argv[4], argc >= 6 ? argv[5] : NULL); + if (i != 0) { + printf("Failed to set variable\n"); + return 1; + } + + return 0; + } + } + +#ifdef CONFIG_PPC + if (strcmp(argv[1], "exec") == 0) { + ulong addr, ramdisk_start, ramdisk_length; + + addr = 0; + ramdisk_start = 0; + ramdisk_length = 0; + + if (argc >= 3) + addr = simple_strtoul(argv[2], NULL, 16); + else if ((value = getenv("loadaddr")) != NULL) + addr = simple_strtoul(value, NULL, 16); + else if ((value = getenv("redboot_kernel_address")) != NULL) + addr = simple_strtoul(value, NULL, 16); + else { + printf("Kernel address not found\n"); + goto usage; + } + + if ((value = getenv("redboot_ramdisk_address")) != NULL) + ramdisk_start = simple_strtoul(value, NULL, 16); + + if ((value = getenv("redboot_ramdisk_length")) != NULL) + ramdisk_length = simple_strtoul(value, NULL, 16); + + redboot_linux_exec(addr, ramdisk_start, ramdisk_length); + } + +#endif + +usage: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + + +U_BOOT_CMD( + redboot, 6, 1, do_redboot, + "redboot - redboot support commands\n", + "select ([bank] [sector] | reset)\n" + " - Select FIS\n" + "redboot fis list\n" + " - List FIS\n" + "redboot fis setenv var type name\n" + " - Set variable var to the type variable of the image\n" + " type: flash_base, mem_base, size, entry_point, data_length\n" + "redboot config printenv [cfgvar] [member]\n" + " - Print Redboot config key(s) of [member] of [cfgvar]\n" + "redboot config setenv var cfgvar [member]\n" + " - Print Redboot config key(s) of [member] of cfgvar\n" +#ifdef CONFIG_PPC + "redboot exec [address]\n" + " - Boot a Linux kernel compiled for redboot\n" +#endif + "" /* last empty string */ +); + +#endif + diff --git a/include/redboot.h b/include/redboot.h new file mode 100644 index 0000000..4fc6315 --- /dev/null +++ b/include/redboot.h @@ -0,0 +1,91 @@ +/* + * (C) Copyright 2006 - Embedded Alley Solutions Inc. + * by Pantelis Antoniou, pantelis@embeddedalley.com + * + * Based on Linux & RedBoot code fragments + * by David Woodhouse, dwmw2@infradead.org + * by Mark Sattler, msalter@redhat.com + * by Gary Thomas, gthomas@redhat.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 + * + */ + +#ifndef REDBOOT_H +#define REDBOOT_H + +#include <common.h> +#include <flash.h> + +struct fis_image_desc { + u8 name[16]; /* Null terminated name */ + u32 flash_base; /* Address within FLASH of image */ + u32 mem_base; /* Address in memory where it executes */ + u32 size; /* Length of image */ + u32 entry_point; /* Execution entry point */ + u32 data_length; /* Length of actual data */ + u8 _pad[256-(16+7*sizeof(unsigned long))]; + u32 desc_cksum; /* Checksum over image descriptor */ + u32 file_cksum; /* Checksum over image data */ +}; + +/* redboot config is stored like this + note that we don't define it, since we can work + without having a fixed size config + +struct redboot_config { + u32 len; + u32 key1; + char config_data[MAX_CONFIG_DATA-(4*4)]; + u32 key2; + u32 long cksum; +}; +*/ + +/* defaults */ +#ifndef CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK +#define CONFIG_REDBOOT_FIS_DIRECTORY_BLOCK -1 /* last block of flash */ +#endif + +#ifndef CONFIG_REDBOOT_DIRECTORY_ENTRY_SIZE +#define CONFIG_REDBOOT_DIRECTORY_ENTRY_SIZE 0x100 /* default */ +#endif + +#ifndef CONFIG_REDBOOT_FLASH_SCRIPT_SIZE +#define CONFIG_REDBOOT_FLASH_SCRIPT_SIZE 256 +#endif + +#ifndef CONFIG_REDBOOT_FLASH_STRING_SIZE +#define CONFIG_REDBOOT_FLASH_STRING_SIZE 128 +#endif + +#ifndef CONFIG_REDBOOT_FLASH_CONFIG_SIZE +#define CONFIG_REDBOOT_FLASH_CONFIG_SIZE 4096 +#endif + +void *redboot_fis_get(int bank, int dir_block, flash_info_t **infop); +int redboot_fis_list(flash_info_t *info, void *fis); +int redboot_fis_entry_lookup(flash_info_t *info, void *fis, struct fis_image_desc *fis_buf, const char *name); +int redboot_fis_setenv(flash_info_t *info, void *fis, const char *name, const char *what, char *var); + +int redboot_config_printenv(flash_info_t *info, void *fis, char *small_buf, const char *what); +const char *redboot_config_getenv(flash_info_t *info, void *fis, char *small_buf, const char *what, const char *special); +int redboot_config_setenv(flash_info_t *info, void *fis, const char *var, const char *what, const char *special); + +#endif

Dear Pantelis,
in message 20061129172559.24638.5730.stgit@pantathon.hol.gr you wrote:
- Print either all the RedBoot config variables or a specific one
> redboot config printenv [config-var] [member]
member is one of value, type, enable-sense, enable-key with value
being the default one.
- Set an environment variable from a RedBoot config variable
> redboot config setenv var config-var [member]
For example when given a config variable of
tsec1_esa=00:08:e5:11:32:33
type=esa enable-sense=true
> redboot config setenv ethaddr tsec1_esa
would set the ethaddr environment variable to 00:08:e5:11:32:33
Can you please explain why you need a separate implementation of printenv / setenv commands? Why do you make a difference between "RedBoot config variables" and normal (U-Boot) environment variables?
> redboot exec address
The PPC bd_t differs for kernels compiled for redboot; this command
lets you boot such a kernel.
I have to admit that I don't like this. I'd rathwer see you using the standard bootm command, and have the necessary adaption done there based on the image type (which should indicate that thgis is a RB image). You have a lot of #ifdef's there anyway.
Also, please cleanup your code (indentation by TABs, trailing white space, C++ comments, line length).
Best regards,
Wolfgang Denk

On 29 Νοε 2006, at 11:21 ΜΜ, Wolfgang Denk wrote:
Hi Wolfgang,
Dear Pantelis,
in message 20061129172559.24638.5730.stgit@pantathon.hol.gr you wrote:
- Print either all the RedBoot config variables or a specific one
> redboot config printenv [config-var] [member]
member is one of value, type, enable-sense, enable-key with
value
being the default one.
- Set an environment variable from a RedBoot config variable
> redboot config setenv var config-var [member]
For example when given a config variable of
tsec1_esa=00:08:e5:11:32:33
type=esa enable-sense=true
> redboot config setenv ethaddr tsec1_esa
would set the ethaddr environment variable to 00:08:e5:11:32:33
Can you please explain why you need a separate implementation of printenv / setenv commands? Why do you make a difference between "RedBoot config variables" and normal (U-Boot) environment variables?
This is not the u-boot environment - it is the RedBoot environment. I am using the RedBoot environment (which is Read-Only) for copying environment variables. Some very important variables are stored there like the ethernet MAC addresses & the ip address.
What this command does is copy the RedBoot config variable to the u- boot ethaddr.
> redboot exec address
The PPC bd_t differs for kernels compiled for redboot; this
command
lets you boot such a kernel.
I have to admit that I don't like this. I'd rathwer see you using the standard bootm command, and have the necessary adaption done there based on the image type (which should indicate that thgis is a RB image). You have a lot of #ifdef's there anyway.
Tried it, didn't work. The amount of defines was getting obscene. As an added bonus the registers used to pass control to the kernel are different, plus you really need to disable the MMU & the caches the way that RedBot does it.
So in conclusion, yes, it is ugly, hacking bootm to make it work is even uglier.
Also, please cleanup your code (indentation by TABs, trailing white space, C++ comments, line length).
Some files were copied verbatim from RedBoot sources, so they are bound to be like this. I've been told that Lattice modifies the FPGA loader regurally, so I tried to keep the original formatting.
Anyway will do.
Best regards,
Wolfgang Denk
-- Software Engineering: Embedded and Realtime Systems, Embedded Linux Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de If all the Chinese simultaneously jumped into the Pacific off a 10 foot platform erected 10 feet off their coast, it would cause a tidal wave that would destroy everything in this country west of Nebraska.
Regards
Pantelis
P.S. Two patches were discarded due to limit size - 40K is pretty small, when there's a single file being 80K. Yes, the FPGA loader file.

In message 22F4C253-E248-41BC-8DEA-76635842B8E6@embeddedalley.com you wrote:
This is not the u-boot environment - it is the RedBoot environment. I am using the RedBoot environment (which is Read-Only) for copying environment variables. Some very important variables are stored there like the ethernet MAC addresses & the ip address.
What this command does is copy the RedBoot config variable to the u- boot ethaddr.
Maybe you could perform a single read and create corresponding entries in the U-Boot environment?
I have to admit that I don't like this. I'd rathwer see you using the standard bootm command, and have the necessary adaption done there based on the image type (which should indicate that thgis is a RB image). You have a lot of #ifdef's there anyway.
Tried it, didn't work. The amount of defines was getting obscene. As an added bonus the registers used to pass control to the kernel are different, plus you really need to disable the MMU & the caches the way that RedBot does it.
Well, maybe you can branch to a different function to handle this?
Also, please cleanup your code (indentation by TABs, trailing white space, C++ comments, line length).
Some files were copied verbatim from RedBoot sources, so they are bound to be like this. I've been told that Lattice modifies the FPGA loader regurally, so I tried to keep the original formatting.
I expected something like this.
Best regards,
Wolfgang Denk

On 30 Νοε 2006, at 12:24 ΠΜ, Wolfgang Denk wrote:
In message 22F4C253-E248-41BC-8DEA-76635842B8E6@embeddedalley.com you wrote:
This is not the u-boot environment - it is the RedBoot environment. I am using the RedBoot environment (which is Read-Only) for copying environment variables. Some very important variables are stored there like the ethernet MAC addresses & the ip address.
What this command does is copy the RedBoot config variable to the u- boot ethaddr.
Maybe you could perform a single read and create corresponding entries in the U-Boot environment?
It would be more complicated really. Each board will need to do it's own thing differently. You would end with a single function doing it with a number of defines for each different board.
Just to make things clear, this is not supposed to be used normally in u-boot; it is targetted for specific boards that need to migrate smoothly to u-boot. There is no cost for other boards.
I have to admit that I don't like this. I'd rathwer see you using the standard bootm command, and have the necessary adaption done there based on the image type (which should indicate that thgis is a RB image). You have a lot of #ifdef's there anyway.
Tried it, didn't work. The amount of defines was getting obscene. As an added bonus the registers used to pass control to the kernel are different, plus you really need to disable the MMU & the caches the way that RedBot does it.
Well, maybe you can branch to a different function to handle this?
Isn't this exactly the same? How would I do that in bootm? I'd use an environment variable to call the different function.
End up with almost the same function & crapping all over bootm.
If anything should be cleaned up is bootm to be split in different functions for the normal & OF case.
IMHO of-course.
Also, please cleanup your code (indentation by TABs, trailing white space, C++ comments, line length).
Some files were copied verbatim from RedBoot sources, so they are bound to be like this. I've been told that Lattice modifies the FPGA loader regurally, so I tried to keep the original formatting.
I expected something like this.
Vendor code = ahem, interesting code :(
Best regards,
Wolfgang Denk
-- Software Engineering: Embedded and Realtime Systems, Embedded Linux Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de Immortality consists largely of boredom. -- Zefrem Cochrane, "Metamorphosis", stardate 3219.8
Regards
Pantelis

Update with my new email address, add as a maintainer of ASP8347DB. Also move NETVIA to unmaintained section.
--- Signed-off-by: Pantelis Antoniou pantelis@embeddedalley.com ---
MAINTAINERS | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS index d453967..c1219ee 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21,9 +21,9 @@ Greg Allen gallen@arlut.utexas.edu
UTX8245 MPC8245
-Pantelis Antoniou panto@intracom.gr +Pantelis Antoniou pantelis@embeddedalley.com
- NETVIA MPC8xx + ASP8347DB MPC834x
Reinhard Arlt reinhard.arlt@esd-electronics.com
@@ -352,6 +352,7 @@ Unknown / orphaned boards: IAD210 MPC8xx MBX MPC8xx MBX860T MPC8xx + NETVIA MPC8xx NX823 MPC8xx RPXClassic MPC8xx RPXlite MPC8xx
participants (3)
-
Pantelis Antoniou
-
Pantelis Antoniou
-
Wolfgang Denk