Skip to contentSkip to conversation

New environment code

PATCH In review Wolfgang Denk 7 participants 53 messages Jul 17, 2010 – Jan 17, 2011 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover New environment code

The following patch series adds some utilities (qsort and hash table based database functions) and uses these to reimplement the code used for the internal handling of environment variables.

Motivation:

* Old environment code used a pessimizing implementation:
- variable lookup used linear search => slow
- changed/added variables were added at the end, i. e. most frequently used variables had the slowest access times => slow
- each setenv() would calculate the CRC32 checksum over the whole environment block => slow
* "redundant" envrionment was locked down to two copies
* No easy way to implement features like "reset to factory defaults", or to select one out of several pre-defined (previously saved) sets of environment settings ("profiles")
* No easy way to import or export environment settings

======================================================================

API Changes:

- Variable names starting with '#' are no longer allowed

I didn't find any such variable names being used; it is highly recommended to follow standard conventions and start variable names with an alphanumeric character

- "printenv" will now print a backslash at the end of all but the last lines of a multi-line variable value.

Multi-line variables have never been formally defined, allthough there is no reason not to use them. Now we define rules how to deal with them, allowing for import and export.

- Function forceenv() and the related code in saveenv() was removed. At the moment this is causing build problems for the only user of this code (schmoogie - which has no entry in MAINTAINERS); may be fixed later by implementing the "env set -f" feature.

Inconsistencies:

- "printenv" will '\\'-escape the '\n' in multi-line variables, while "printenv var" will not do that.

======================================================================

Advantages:

- "printenv" output much better readable (sorted)
- faster!
- extendable (additional variable properties can be added)
- new, powerful features like "factory reset" or easy switching between several different environment settings ("profiles")

Disadvantages:

- Image size grows by typically 5...7 KiB (might shrink a bit again on systems with redundant environment with a following patch series)

======================================================================

Implemented:

- env command with subcommands:

- env print [arg ...]

same as "printenv": print environment

- env set [-f] name [arg ...]

same as "setenv": set (and delete) environment variables

["-f" - force setting even for read-only variables - not implemented yet.]

- end delete [-f] name

not implemented yet

["-f" - force delete even for read-only variables]

- env save

same as "saveenv": save environment

- env export [-t | -b | -c] addr [size]

export internal representation (hash table) in formats usable for persistent storage or processing:

-t: export as text format; if size is given, data will be
padded with '\0' bytes; if not, one terminating '\0' will be added (which is included in the "filesize" setting so you can for exmple copy this to flash and keep the termination).
-b: export as binary format (name=value pairs separated by
'\0', list end marked by double "\0\0")
-c: export as checksum protected environment format as
used for example by "saveenv" command
addr: memory address where environment gets stored
size: size of output buffer

With "-c" and size is NOT given, then the export command will format the data as currently used for the persistent storage, i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and prepend a valid CRC32 checksum and, in case of resundant environment, a "current" redundancy flag. If size is given, this value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 checksum and redundancy flag will be inserted.

With "-b" and "-t", always only the real data (including a terminating '\0' byte) will be written; here the optional size argument will be used to make sure not to overflow the user provided buffer; the command will abort if the size is not sufficient. Any remainign space will be '\0' padded.

On successful return, the variable "filesize" will be set. Note that filesize includes the trailing/terminating '\0' byte(s).

Usage szenario: create a text snapshot/backup of the current settings:

=> env export -t 100000
=> era ${backup_addr} +${filesize} => cp.b 100000 ${backup_addr} ${filesize}

Re-import this snapshot, deleting all other settings:

=> env import -d -t ${backup_addr}

- env import [-d] [-t | -b | -c] addr [size]

import external format (text or binary) into hash table, optionally deleting existing values:

-d: delete existing environment before importing;
otherwise overwrite / append to existion definitions
-t: assume text format; either "size" must be given or the
text data must be '\0' terminated
-b: assume binary format ('\0' separated, "\0\0" terminated)
-c: assume checksum protected environment format
addr: memory address to read from
size: length of input data; if missing, proper '\0'
termination is mandatory

- env default -f

reset default environment: drop all environment settings and load default environment

- env ask name [message] [size]

same as "askenv": ask for environment variable

- env edit name

same as "editenv": edit environment variable

- env run

same as "run": run commands in an environment variable

======================================================================

TODO:

- drop default env as implemented now; provide a text file based initialization instead (eventually using several text files to incrementally build it from common blocks) and a tool to convert it into a binary blob / object file.

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

- Some boards don't link any more due to the grown code size:
AR405, CANBT, DU405, PMC440, canyonlands, sc3, sequoia, socrates.

=> cc: Matthias Fuchs <[email protected]>,
Stefan Roese <[email protected]>,
Heiko Schocher <[email protected]>

- Dropping forceenv() causes build problems on schmoogie

=> cc: Sergey Kubushyn <[email protected]>

- Build tested on PPC and ARM only; runtime tested with NOR and NAND flash only => needs testing!!

Wolfgang Denk (5):
Add basic errno support.
Add qsort - add support for sorting data arrays
Add hash table support as base for new environment code Remove support for CONFIG_HAS_UID and "forceenv" command New implementation for internal handling of environment variables.

 README                              |    8 +
 board/zeus/zeus.c                   |   25 +-
 common/cmd_nvedit.c                 |  668 ++++++++++++++++++++++----------
 common/command.c                    |    3 +-
 common/dlmalloc.c                   |   25 +-
 common/env_common.c                 |  125 +++---
 common/env_dataflash.c              |  114 ++++--
 common/env_eeprom.c                 |   85 +++--
 common/env_flash.c                  |  245 +++++++------
 common/env_mgdisk.c                 |   33 +-
 common/env_nand.c                   |  188 +++++----
 common/env_nowhere.c                |   11 +-
 common/env_nvram.c                  |   46 ++-
 common/env_onenand.c                |   65 ++--
 common/env_sf.c                     |  132 ++++---
 common/exports.c                    |    4 -
 include/_exports.h                  |    1 -
 include/common.h                    |    7 +-
 include/configs/MVSMR.h             |    1 -
 include/configs/davinci_schmoogie.h |    1 -
 include/environment.h               |    5 +-
 include/errno.h                     |    9 +
 include/exports.h                   |    3 -
 include/search.h                    |  106 +++++
 lib/Makefile                        |    3 +
 lib/errno.c                         |    1 +
 lib/hashtable.c                     |  735 +++++++++++++++++++++++++++++++++++
 lib/qsort.c                         |   69 ++++
 28 files changed, 1998 insertions(+), 720 deletions(-)
 create mode 100644 include/errno.h
 create mode 100644 include/search.h
 create mode 100644 lib/errno.c
 create mode 100644 lib/hashtable.c
 create mode 100644 lib/qsort.c
#1 lore raw

PATCH 1/5 Add basic errno support.

Needed for hash table support; probably useful in a lot of other places as well.

---
 include/errno.h |    9 +++++++++
 lib/Makefile    |    1 +
 lib/errno.c     |    1 +
 3 files changed, 11 insertions(+), 0 deletions(-)
 create mode 100644 include/errno.h
 create mode 100644 lib/errno.c
include/errno.h new file +9 -0
new file mode 100644
index 0000000..e24a33b
@@ -0,0 +1,9 @@
+#ifndef _ERRNO_H
+
+#include <asm-generic/errno.h>
+
+extern int errno;
+
+#define __set_errno(val) do { errno = val; } while (0)
+
+#endif /* _ERRNO_H */
lib/Makefile +1 -0
index c45f07c..c26536d 100644
@@ -37,6 +37,7 @@ COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += display_options.o
 COBJS-y += div64.o
+COBJS-y += errno.o
 COBJS-$(CONFIG_GZIP) += gunzip.o
 COBJS-$(CONFIG_LMB) += lmb.o
 COBJS-y += ldiv.o
lib/errno.c new file +1 -0
new file mode 100644
index 0000000..8330a8f
@@ -0,0 +1 @@
+int errno = 0;
Signature · 1 line
1.7.1.1
#2 lore raw

PATCH 1/5 Add basic errno support.

lib/errno.c line 1

Quoted 4 lines · On Saturday, July 17, 2010 15:45:44 Wolfgang Denk wrote:
lib/errno.c new file +1 -0
@@ -0,0 +1 @@
+int errno = 0;

drop the "= 0" so that errno ends up in the bss ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100717/d5508909/attachment.pgp

#3 lore raw

PATCH 1/5 Add basic errno support.

Dear Mike Frysinger,

Quoted 6 lines · In message <[email protected]> you wrote:

lib/errno.c line 1

Quoted 4 lines

+++ b/lib/errno.c

lib/errno.c new file +1 -0
@@ -0,0 +1 @@
+int errno = 0;

drop the "= 0" so that errno ends up in the bss ?

This does not make any difference; the tools are clever enough to figure that out:

	-> nm lib/errno.o
	00000000 S errno

S = "The symbol is in an uninitialized data section for small objects."

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A quarrel is quickly settled when deserted by one party; there is  no
battle unless there be two.                                  - Seneca
#4 lore raw

PATCH 1/5 Add basic errno support.

In reply to Mike Frysinger
Quoted 8 lines · Mike Frysinger

lib/errno.c line 1

Quoted 4 lines · On Saturday, July 17, 2010 15:45:44 Wolfgang Denk wrote:
lib/errno.c new file +1 -0
@@ -0,0 +1 @@
+int errno = 0;

drop the "= 0" so that errno ends up in the bss ?
-mike

Is this going to be a problem during early startup (pre-relocation) vs. normal running? Pre-relocation, we only have a temporary stack and RAM is not set up initially.

I have not looked at when RAM gets initialized vs. when env. variables get used. It is probably OK. Wolfgang?

Best regards,
gvb

#5 lore raw

PATCH 1/5 Add basic errno support.

Dear Jerry Van Baren,

Quoted 10 lines · In message <[email protected]> you wrote:
Quoted 3 lines

drop the "= 0" so that errno ends up in the bss ?
-mike

Is this going to be a problem during early startup (pre-relocation) vs. normal running? Pre-relocation, we only have a temporary stack and RAM is not set up initially.

I have not looked at when RAM gets initialized vs. when env. variables get used. It is probably OK. Wolfgang?

AFAICT the relevant code runs all only after relocation to RAM, i. e. the use of errno (whether in BSS or not) should be no problem.

But you are right - using it before relocation will not work as is. We could make it a global data entry, if needed.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Free markets select for winning solutions."        - Eric S. Raymond
author Applied
#6 lore raw

PATCH 1/5 Add basic errno support.

In reply to Wolfgang Denk

Dear Wolfgang Denk,

Quoted 11 lines · In message <[email protected]> you wrote:

Needed for hash table support; probably useful in a lot of other places as well.

---
 include/errno.h |    9 +++++++++
 lib/Makefile    |    1 +
 lib/errno.c     |    1 +
 3 files changed, 11 insertions(+), 0 deletions(-)
 create mode 100644 include/errno.h
 create mode 100644 lib/errno.c

Applied to "next" branch.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"Send lawyers, guns and money..."  - Lyrics from a Warren Zevon song
#7 lore raw

PATCH 2/5 Add qsort - add support for sorting data arrays

In reply to Wolfgang Denk

Code adapted from uClibc-0.9.30.3

---
 include/common.h |    4 +++
 lib/Makefile     |    1 +
 lib/qsort.c      |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 0 deletions(-)
 create mode 100644 lib/qsort.c
include/common.h +4 -0
index eddec22..e4b4ec0 100644
@@ -631,6 +631,10 @@ static inline IPaddr_t getenv_IPaddr (char *var)
 	return (string_to_ip(getenv(var)));
 }
 
+/* lib/qsort.c */
+void qsort(void *base, size_t nmemb, size_t size,
+	   int(*compar)(const void *, const void *));
+
 /* lib/time.c */
 void	udelay        (unsigned long);
 
lib/Makefile +1 -0
index c26536d..2d969a3 100644
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_LMB) += lmb.o
 COBJS-y += ldiv.o
 COBJS-$(CONFIG_MD5) += md5.o
 COBJS-y += net_utils.o
+COBJS-y += qsort.o
 COBJS-$(CONFIG_SHA1) += sha1.o
 COBJS-$(CONFIG_SHA256) += sha256.o
 COBJS-y += string.o
lib/qsort.c new file +69 -0

69 lines not on this page · raw message

Signature · 1 line
1.7.1.1
author Applied
#8 lore raw

PATCH 2/5 Add qsort - add support for sorting data arrays

Dear Wolfgang Denk,

Quoted 9 lines · In message <[email protected]> you wrote:

Code adapted from uClibc-0.9.30.3

---
 include/common.h |    4 +++
 lib/Makefile     |    1 +
 lib/qsort.c      |   69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 74 insertions(+), 0 deletions(-)
 create mode 100644 lib/qsort.c

Applied to "next" branch.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
F u cn rd ths u cnt spl wrth a dm!
#9 lore raw

PATCH 3/5 Add hash table support as base for new environment code

In reply to Wolfgang Denk

This implementation is based on code from uClibc-0.9.30.3 but was modified and extended for use within U-Boot.

Major modifications and extensions:

* hsearch() [modified / extended]:
- While the standard version does not make any assumptions about the type of the stored data objects at all, this implementation works with NUL terminated strings only.
- Instead of storing just pointers to the original objects, we create local copies so the caller does not need to care about the data any more.
- The standard implementation does not provide a way to update an existing entry. This version will create a new entry or update an existing one when both "action == ENTER" and "item.data != NULL".
- hsearch_r(): Instead of returning 1 on success, we return the index into the internal hash table, which is also guaranteed to be positive. This allows us direct access to the found hash table slot for example for functions like hdelete().
* hdelete() [added]:
- The standard implementation of hsearch(3) does not provide any way to delete any entries from the hash table. We extend the code to do that.
* hexport() [added]:
- Export the data stored in the hash table in linearized form:
Entries are exported as "name=value" strings, separated by an arbitrary (non-NUL, of course) separator character. This allows to use this function both when formatting the U-Boot environment for external storage (using '\0' as separator), but also when using it for the "printenv" command to print all variables, simply by using as '\n" as separator. This can also be used for new features like exporting the environment data as text file, including the option for later re-import.
- The entries in the result list will be sorted by ascending key values.
* himport() [added]:
- Import linearized data into hash table. This is the inverse function to hexport(): it takes a linear list of "name=value" pairs and creates hash table entries from it.
- Entries without "value", i. e. consisting of only "name" or "name=", will cause this entry to be deleted from the hash table.
- The "flag" argument can be used to control the behaviour: when the H_NOCLEAR bit is set, then an existing hash table will kept, i. e. new data will be added to an existing hash table; otherwise, old data will be discarded and a new hash table will be created.
- The separator character for the "name=value" pairs can be selected, so we both support importing from externally stored environment data (separated by NUL characters) and from plain text files (entries separated by newline characters).
- To allow for nicely formatted text input, leading white space (sequences of SPACE and TAB chars) is ignored, and entries starting (after removal of any leading white space) with a '#' character are considered comments and ignored.
- NOTE: this means that a variable name cannot start with a '#' character.
- When using a non-NUL separator character, backslash is used as escape character in the value part, allowing for example fo multi-line values.
- In theory, arbitrary separator characters can be used, but only '\0' and '\n' have really been tested.

---
 include/search.h |  106 ++++++++
 lib/Makefile     |    1 +
 lib/hashtable.c  |  721 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 828 insertions(+), 0 deletions(-)
 create mode 100644 include/search.h
 create mode 100644 lib/hashtable.c
include/search.h new file +106 -0
new file mode 100644
index 0000000..fccc757
@@ -0,0 +1,106 @@
+/*
+ * Declarations for System V style searching functions.
+ * Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307 USA.
+ */
+
+/*
+ * Based on code from uClibc-0.9.30.3
+ * Extensions for use within U-Boot
+ * Copyright (C) 2010 Wolfgang Denk <[email protected]>
+ */
+
+#ifndef _SEARCH_H
+#define	_SEARCH_H 1
+
+#include <stddef.h>
+
+#define __set_errno(val) do { errno = val; } while (0)
+
+/*
+ * Prototype structure for a linked-list data structure.
+ * This is the type used by the `insque' and `remque' functions.
+ */
+
+/* For use with hsearch(3).  */
+typedef int (*__compar_fn_t) (__const void *, __const void *);
+typedef __compar_fn_t comparison_fn_t;
+
+/* Action which shall be performed in the call the hsearch.  */
+typedef enum {
+	FIND,
+	ENTER
+} ACTION;
+
+typedef struct entry {
+	char *key;
+	char *data;
+} ENTRY;
+
+/* Opaque type for internal use.  */
+struct _ENTRY;
+
+/*
+ * Family of hash table handling functions.  The functions also
+ * have reentrant counterparts ending with _r.  The non-reentrant
+ * functions all work on a signle internal hashing table.
+ */
+
+/* Data type for reentrant functions.  */
+struct hsearch_data {
+	struct _ENTRY *table;
+	unsigned int size;
+	unsigned int filled;
+};
+
+/* Create a new hashing table which will at most contain NEL elements.  */
+extern int hcreate(size_t __nel);
+extern int hcreate_r(size_t __nel, struct hsearch_data *__htab);
+
+/* Destroy current internal hashing table.  */
+extern void hdestroy(void);
+extern void hdestroy_r(struct hsearch_data *__htab);
+
+/*
+ * Search for entry matching ITEM.key in internal hash table.  If
+ * ACTION is `FIND' return found entry or signal error by returning
+ * NULL.  If ACTION is `ENTER' replace existing data (if any) with
+ * ITEM.data.
+ * */
+extern ENTRY *hsearch(ENTRY __item, ACTION __action);
+extern int hsearch_r(ENTRY __item, ACTION __action, ENTRY ** __retval,
+		     struct hsearch_data *__htab);
+
+/* Search and delete entry matching ITEM.key in internal hash table. */
+extern int hdelete(const char *__key);
+extern int hdelete_r(const char *__key, struct hsearch_data *__htab);
+
+extern ssize_t hexport(const char __sep, char **__resp, size_t __size);
+extern ssize_t hexport_r(struct hsearch_data *__htab,
+		     const char __sep, char **__resp, size_t __size);
+
+extern int himport(const char *__env, size_t __size, const char __sep,
+		   int __flag);
+extern int himport_r(struct hsearch_data *__htab,
+		     const char *__env, size_t __size, const char __sep,
+		     int __flag);
+
+/* Flags for himport() / himport_r() */
+#define	H_NOCLEAR	1	/* do not clear hash table before importing */
+
+#endif /* search.h */
lib/Makefile +1 -0
index 2d969a3..a8de3e1 100644
@@ -39,6 +39,7 @@ COBJS-y += display_options.o
 COBJS-y += div64.o
 COBJS-y += errno.o
 COBJS-$(CONFIG_GZIP) += gunzip.o
+COBJS-y += hashtable.o
 COBJS-$(CONFIG_LMB) += lmb.o
 COBJS-y += ldiv.o
 COBJS-$(CONFIG_MD5) += md5.o
lib/hashtable.c new file +721 -0

721 lines not on this page · raw message

Signature · 1 line
1.7.1.1
author Applied
#10 lore raw

PATCH 3/5 Add hash table support as base for new environment code

Dear Wolfgang Denk,

Quoted 62 lines · In message <[email protected]> you wrote:

This implementation is based on code from uClibc-0.9.30.3 but was modified and extended for use within U-Boot.

Major modifications and extensions:

* hsearch() [modified / extended]:
- While the standard version does not make any assumptions about the type of the stored data objects at all, this implementation works with NUL terminated strings only.
- Instead of storing just pointers to the original objects, we create local copies so the caller does not need to care about the data any more.
- The standard implementation does not provide a way to update an existing entry. This version will create a new entry or update an existing one when both "action == ENTER" and "item.data != NULL".
- hsearch_r(): Instead of returning 1 on success, we return the index into the internal hash table, which is also guaranteed to be positive. This allows us direct access to the found hash table slot for example for functions like hdelete().
* hdelete() [added]:
- The standard implementation of hsearch(3) does not provide any way to delete any entries from the hash table. We extend the code to do that.
* hexport() [added]:
- Export the data stored in the hash table in linearized form:
Entries are exported as "name=value" strings, separated by an arbitrary (non-NUL, of course) separator character. This allows to use this function both when formatting the U-Boot environment for external storage (using '\0' as separator), but also when using it for the "printenv" command to print all variables, simply by using as '\n" as separator. This can also be used for new features like exporting the environment data as text file, including the option for later re-import.
- The entries in the result list will be sorted by ascending key values.
* himport() [added]:
- Import linearized data into hash table. This is the inverse function to hexport(): it takes a linear list of "name=value" pairs and creates hash table entries from it.
- Entries without "value", i. e. consisting of only "name" or "name=", will cause this entry to be deleted from the hash table.
- The "flag" argument can be used to control the behaviour: when the H_NOCLEAR bit is set, then an existing hash table will kept, i. e. new data will be added to an existing hash table; otherwise, old data will be discarded and a new hash table will be created.
- The separator character for the "name=value" pairs can be selected, so we both support importing from externally stored environment data (separated by NUL characters) and from plain text files (entries separated by newline characters).
- To allow for nicely formatted text input, leading white space (sequences of SPACE and TAB chars) is ignored, and entries starting (after removal of any leading white space) with a '#' character are considered comments and ignored.
- NOTE: this means that a variable name cannot start with a '#' character.
- When using a non-NUL separator character, backslash is used as escape character in the value part, allowing for example fo multi-line values.
- In theory, arbitrary separator characters can be used, but only '\0' and '\n' have really been tested.

Quoted 8 lines
---
 include/search.h |  106 ++++++++
 lib/Makefile     |    1 +
 lib/hashtable.c  |  721 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 828 insertions(+), 0 deletions(-)
 create mode 100644 include/search.h
 create mode 100644 lib/hashtable.c

Applied to "next" branch.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
It seems intuitively obvious to me, which  means  that  it  might  be
wrong.                                                 -- Chris Torek
#11 lore raw

PATCH 3/5 Add hash table support as base for new environment code

In reply to Wolfgang Denk
Quoted 2 lines · On Saturday, July 17, 2010 15:45:46 Wolfgang Denk wrote:

This implementation is based on code from uClibc-0.9.30.3 but was modified and extended for use within U-Boot.

unless i'm missing something, the non-reentrant versions operate on a single shared hash table. so while this works today because there is only one consumer (the env code), wont this cause problems as soon as someone else tries to use the non-reentrant hash table code ? as such, wouldnt it make sense to punt all of the non-reentrant versions and thus force everyone to maintain their own "struct hsearch_data" instance ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101208/3d9a27f3/attachment.pgp

#12 lore raw

PATCH 3/5 Add hash table support as base for new environment code

Dear Mike Frysinger,

Quoted 3 lines · In message <[email protected]> you wrote:

unless i'm missing something, the non-reentrant versions operate on a single shared hash table. so while this works today because there is only one

Correct.

Quoted 4 lines

consumer (the env code), wont this cause problems as soon as someone else tries to use the non-reentrant hash table code ? as such, wouldnt it make sense to punt all of the non-reentrant versions and thus force everyone to maintain their own "struct hsearch_data" instance ?

This could be done, but I don't see an immediate need.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I've already got a female to worry about. Her name is the Enterprise.
	-- Kirk, "The Corbomite Maneuver", stardate 1514.0
#13 lore raw

PATCH 3/5 Add hash table support as base for new environment code

Quoted 5 lines · On Wednesday, December 08, 2010 05:02:38 Wolfgang Denk wrote:
Quoted 3 lines · Mike Frysinger

unless i'm missing something, the non-reentrant versions operate on a single shared hash table. so while this works today because there is only one

Quoted 8 lines

Correct.

Quoted 4 lines

consumer (the env code), wont this cause problems as soon as someone else tries to use the non-reentrant hash table code ? as such, wouldnt it make sense to punt all of the non-reentrant versions and thus force everyone to maintain their own "struct hsearch_data" instance ?

This could be done, but I don't see an immediate need.

off the top of my head:
- it isnt obvious to people today that this issue exists, so anyone
attempting to use the fun new hashtable code could conceivably use it without running into a problem (as long as their keys dont happen to collide with env names). so people could possibly waste quite a bit of their time trying to track down bugs that only crop up when certain env vars are set.
- i imagine a bit of space is being wasted here.
- i re-implemented env-autocomplete, but i need access to the hashtable
structure where everything is stored.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101208/f9f23b19/attachment.pgp

#14 lore raw

PATCH 4/5 Remove support for CONFIG_HAS_UID and "forceenv" command

In reply to Wolfgang Denk

This (undocumented) concept was only in use for the MVSMR and davinci_schmoogie Sergey Kubushyn <[email protected]> boards. Drop it for now. If really needed, it should be reimplemented later in the context of the new environment command set.

Cc Andre Schwarz <[email protected]>
Cc Sergey Kubushyn <[email protected]>
---
 common/cmd_nvedit.c                 |   13 -------------
 common/exports.c                    |    3 ---
 include/_exports.h                  |    1 -
 include/common.h                    |    3 ---
 include/configs/MVSMR.h             |    1 -
 include/configs/davinci_schmoogie.h |    1 -
 include/exports.h                   |    3 ---
 7 files changed, 0 insertions(+), 25 deletions(-)
common/cmd_nvedit.c +0 -13
index 13325bc..8c86f15 100644
@@ -247,12 +247,7 @@ int _do_setenv (int flag, int argc, char * const argv[])
 		 * ver is readonly.
 		 */
 		if (
-#ifdef CONFIG_HAS_UID
-		/* Allow serial# forced overwrite with 0xdeaf4add flag */
-		    ((strcmp (name, "serial#") == 0) && (flag != 0xdeaf4add)) ||
-#else
 		    (strcmp (name, "serial#") == 0) ||
-#endif
 		    ((strcmp (name, "ethaddr") == 0)
 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
 		     && (strcmp ((char *)env_get_addr(oldval),MK_STR(CONFIG_ETHADDR)) != 0)
@@ -397,14 +392,6 @@ int setenv (char *varname, char *varvalue)
 		return _do_setenv (0, 3, argv);
 }
 
-#ifdef CONFIG_HAS_UID
-void forceenv (char *varname, char *varvalue)
-{
-	char * const argv[4] = { "forceenv", varname, varvalue, NULL };
-	_do_setenv (0xdeaf4add, 3, argv);
-}
-#endif
-
 int do_setenv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	if (argc < 2) {
common/exports.c +0 -3
index cefe6f6..bde52a6 100644
@@ -35,9 +35,6 @@ unsigned long get_version(void)
 # define spi_release_bus   dummy
 # define spi_xfer          dummy
 #endif
-#ifndef CONFIG_HAS_UID
-# define forceenv          dummy
-#endif
 
 void jumptable_init(void)
 {
include/_exports.h +0 -1
index f3df568..d89b65b 100644
@@ -18,7 +18,6 @@ EXPORT_FUNC(vprintf)
 EXPORT_FUNC(do_reset)
 EXPORT_FUNC(getenv)
 EXPORT_FUNC(setenv)
-EXPORT_FUNC(forceenv)
 EXPORT_FUNC(simple_strtoul)
 EXPORT_FUNC(simple_strtol)
 EXPORT_FUNC(strcmp)
include/common.h +0 -3
index e4b4ec0..5eef9c7 100644
@@ -262,9 +262,6 @@ int	saveenv	     (void);
 int inline setenv   (char *, char *);
 #else
 int	setenv	     (char *, char *);
-#ifdef CONFIG_HAS_UID
-void	forceenv     (char *, char *);
-#endif
 #endif /* CONFIG_PPC */
 #ifdef CONFIG_ARM
 # include <asm/mach-types.h>
include/configs/MVSMR.h +0 -1
index 6492068..000c4c6 100644
@@ -185,7 +185,6 @@
  */
 #define CONFIG_ENV_IS_IN_FLASH
 #undef	CONFIG_SYS_FLASH_PROTECTION
-#define CONFIG_HAS_UID
 #define	CONFIG_OVERWRITE_ETHADDR_ONCE
 
 #define CONFIG_ENV_OFFSET	0x8000
include/configs/davinci_schmoogie.h +0 -1
index 875dda4..04cdc21 100644
@@ -99,7 +99,6 @@
 /*=====================*/
 #define CONFIG_RTC_DS1307		/* RTC chip on SCHMOOGIE */
 #define CONFIG_SYS_I2C_RTC_ADDR	0x6f	/* RTC chip I2C address */
-#define CONFIG_HAS_UID
 #define CONFIG_UID_DS28CM00		/* Unique ID on SCHMOOGIE */
 #define CONFIG_SYS_UID_ADDR		0x50	/* UID chip I2C address */
 /*==============================*/
include/exports.h +0 -3
index 1d79a31..7404a7c 100644
@@ -26,9 +26,6 @@ int setenv (char *varname, char *varvalue);
 long simple_strtol(const char *cp,char **endp,unsigned int base);
 int strcmp(const char * cs,const char * ct);
 int ustrtoul(const char *cp, char **endp, unsigned int base);
-#ifdef CONFIG_HAS_UID
-void forceenv (char *varname, char *varvalue);
-#endif
 #if defined(CONFIG_CMD_I2C)
 int i2c_write (uchar, uint, int , uchar* , int);
 int i2c_read (uchar, uint, int , uchar* , int);
Signature · 1 line
1.7.1.1
#15 lore raw

PATCH 4/5 Remove support for CONFIG_HAS_UID and "forceenv" command

On Sat, 17 Jul 2010, Wolfgang Denk wrote:

Ack by: Sergey Kubushyn <[email protected]>
---

Quoted 131 lines

This (undocumented) concept was only in use for the MVSMR and davinci_schmoogie Sergey Kubushyn <[email protected]> boards. Drop it for now. If really needed, it should be reimplemented later in the context of the new environment command set.

Cc Andre Schwarz <[email protected]>
Cc Sergey Kubushyn <[email protected]>

---

common/cmd_nvedit.c                 |   13 -------------
common/exports.c                    |    3 ---
include/_exports.h                  |    1 -
include/common.h                    |    3 ---
include/configs/MVSMR.h             |    1 -
include/configs/davinci_schmoogie.h |    1 -
include/exports.h                   |    3 ---
7 files changed, 0 insertions(+), 25 deletions(-)
common/cmd_nvedit.c +0 -13
index 13325bc..8c86f15 100644
@@ -247,12 +247,7 @@ int _do_setenv (int flag, int argc, char * const argv[])
 		 * ver is readonly.
 		 */
 		if (
-#ifdef CONFIG_HAS_UID
-		/* Allow serial# forced overwrite with 0xdeaf4add flag */
-		    ((strcmp (name, "serial#") == 0) && (flag != 0xdeaf4add)) ||
-#else
 		    (strcmp (name, "serial#") == 0) ||
-#endif
 		    ((strcmp (name, "ethaddr") == 0)
 #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
 		     && (strcmp ((char *)env_get_addr(oldval),MK_STR(CONFIG_ETHADDR)) != 0)
@@ -397,14 +392,6 @@ int setenv (char *varname, char *varvalue)
 		return _do_setenv (0, 3, argv);
 }
 
-#ifdef CONFIG_HAS_UID
-void forceenv (char *varname, char *varvalue)
-{
-	char * const argv[4] = { "forceenv", varname, varvalue, NULL };
-	_do_setenv (0xdeaf4add, 3, argv);
-}
-#endif
-
 int do_setenv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	if (argc < 2) {
common/exports.c +0 -3
index cefe6f6..bde52a6 100644
@@ -35,9 +35,6 @@ unsigned long get_version(void)
 # define spi_release_bus   dummy
 # define spi_xfer          dummy
 #endif
-#ifndef CONFIG_HAS_UID
-# define forceenv          dummy
-#endif
 
 void jumptable_init(void)
 {
include/_exports.h +0 -1
index f3df568..d89b65b 100644
@@ -18,7 +18,6 @@ EXPORT_FUNC(vprintf)
 EXPORT_FUNC(do_reset)
 EXPORT_FUNC(getenv)
 EXPORT_FUNC(setenv)
-EXPORT_FUNC(forceenv)
 EXPORT_FUNC(simple_strtoul)
 EXPORT_FUNC(simple_strtol)
 EXPORT_FUNC(strcmp)
include/common.h +0 -3
index e4b4ec0..5eef9c7 100644
@@ -262,9 +262,6 @@ int	saveenv	     (void);
 int inline setenv   (char *, char *);
 #else
 int	setenv	     (char *, char *);
-#ifdef CONFIG_HAS_UID
-void	forceenv     (char *, char *);
-#endif
 #endif /* CONFIG_PPC */
 #ifdef CONFIG_ARM
 # include <asm/mach-types.h>
include/configs/MVSMR.h +0 -1
index 6492068..000c4c6 100644
@@ -185,7 +185,6 @@
 */
 #define CONFIG_ENV_IS_IN_FLASH
 #undef	CONFIG_SYS_FLASH_PROTECTION
-#define CONFIG_HAS_UID
 #define	CONFIG_OVERWRITE_ETHADDR_ONCE
 
 #define CONFIG_ENV_OFFSET	0x8000
include/configs/davinci_schmoogie.h +0 -1
index 875dda4..04cdc21 100644
@@ -99,7 +99,6 @@
 /*=====================*/
 #define CONFIG_RTC_DS1307		/* RTC chip on SCHMOOGIE */
 #define CONFIG_SYS_I2C_RTC_ADDR	0x6f	/* RTC chip I2C address */
-#define CONFIG_HAS_UID
 #define CONFIG_UID_DS28CM00		/* Unique ID on SCHMOOGIE */
 #define CONFIG_SYS_UID_ADDR		0x50	/* UID chip I2C address */
 /*==============================*/
include/exports.h +0 -3
index 1d79a31..7404a7c 100644
@@ -26,9 +26,6 @@ int setenv (char *varname, char *varvalue);
 long simple_strtol(const char *cp,char **endp,unsigned int base);
 int strcmp(const char * cs,const char * ct);
 int ustrtoul(const char *cp, char **endp, unsigned int base);
-#ifdef CONFIG_HAS_UID
-void forceenv (char *varname, char *varvalue);
-#endif
 #if defined(CONFIG_CMD_I2C)
 int i2c_write (uchar, uint, int , uchar* , int);
 int i2c_read (uchar, uint, int , uchar* , int);
Signature · 1 line
1.7.1.1

---
******************************************************************
* KSI at home KOI8 Net < > The impossible we do immediately. *
* Las Vegas NV, USA < > Miracles require 24-hour notice. *
******************************************************************

author Applied
#16 lore raw

PATCH 4/5 Remove support for CONFIG_HAS_UID and "forceenv" command

In reply to Wolfgang Denk

Dear Wolfgang Denk,

Quoted 8 lines · In message <[email protected]> you wrote:

This (undocumented) concept was only in use for the MVSMR and davinci_schmoogie Sergey Kubushyn <[email protected]> boards. Drop it for now. If really needed, it should be reimplemented later in the context of the new environment command set.

Cc Andre Schwarz <[email protected]>
Cc Sergey Kubushyn <[email protected]>
Quoted 9 lines
---
 common/cmd_nvedit.c                 |   13 -------------
 common/exports.c                    |    3 ---
 include/_exports.h                  |    1 -
 include/common.h                    |    3 ---
 include/configs/MVSMR.h             |    1 -
 include/configs/davinci_schmoogie.h |    1 -
 include/exports.h                   |    3 ---
 7 files changed, 0 insertions(+), 25 deletions(-)

Applied to "next" branch.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
It may be that your whole purpose in life is simply  to  serve  as  a
warning to others.
#17 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

In reply to Wolfgang Denk

Motivation:

* Old environment code used a pessimizing implementation:
- variable lookup used linear search => slow
- changed/added variables were added at the end, i. e. most frequently used variables had the slowest access times => slow
- each setenv() would calculate the CRC32 checksum over the whole environment block => slow
* "redundant" envrionment was locked down to two copies
* No easy way to implement features like "reset to factory defaults", or to select one out of several pre-defined (previously saved) sets of environment settings ("profiles")
* No easy way to import or export environment settings

======================================================================

API Changes:

- Variable names starting with '#' are no longer allowed

I didn't find any such variable names being used; it is highly recommended to follow standard conventions and start variable names with an alphanumeric character

- "printenv" will now print a backslash at the end of all but the last lines of a multi-line variable value.

Multi-line variables have never been formally defined, allthough there is no reason not to use them. Now we define rules how to deal with them, allowing for import and export.

- Function forceenv() and the related code in saveenv() was removed. At the moment this is causing build problems for the only user of this code (schmoogie - which has no entry in MAINTAINERS); may be fixed later by implementing the "env set -f" feature.

Inconsistencies:

- "printenv" will '\\'-escape the '\n' in multi-line variables, while "printenv var" will not do that.

======================================================================

Advantages:

- "printenv" output much better readable (sorted)
- faster!
- extendable (additional variable properties can be added)
- new, powerful features like "factory reset" or easy switching between several different environment settings ("profiles")

Disadvantages:

- Image size grows by typically 5...7 KiB (might shrink a bit again on systems with redundant environment with a following patch series)

======================================================================

Implemented:

- env command with subcommands:

- env print [arg ...]

same as "printenv": print environment

- env set [-f] name [arg ...]

same as "setenv": set (and delete) environment variables

["-f" - force setting even for read-only variables - not implemented yet.]

- end delete [-f] name

not implemented yet

["-f" - force delete even for read-only variables]

- env save

same as "saveenv": save environment

- env export [-t | -b | -c] addr [size]

export internal representation (hash table) in formats usable for persistent storage or processing:

-t: export as text format; if size is given, data will be
padded with '\0' bytes; if not, one terminating '\0' will be added (which is included in the "filesize" setting so you can for exmple copy this to flash and keep the termination).
-b: export as binary format (name=value pairs separated by
'\0', list end marked by double "\0\0")
-c: export as checksum protected environment format as
used for example by "saveenv" command
addr: memory address where environment gets stored
size: size of output buffer

With "-c" and size is NOT given, then the export command will format the data as currently used for the persistent storage, i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and prepend a valid CRC32 checksum and, in case of resundant environment, a "current" redundancy flag. If size is given, this value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 checksum and redundancy flag will be inserted.

With "-b" and "-t", always only the real data (including a terminating '\0' byte) will be written; here the optional size argument will be used to make sure not to overflow the user provided buffer; the command will abort if the size is not sufficient. Any remainign space will be '\0' padded.

On successful return, the variable "filesize" will be set. Note that filesize includes the trailing/terminating '\0' byte(s).

Usage szenario: create a text snapshot/backup of the current settings:

=> env export -t 100000
=> era ${backup_addr} +${filesize} => cp.b 100000 ${backup_addr} ${filesize}

Re-import this snapshot, deleting all other settings:

=> env import -d -t ${backup_addr}

- env import [-d] [-t | -b | -c] addr [size]

import external format (text or binary) into hash table, optionally deleting existing values:

-d: delete existing environment before importing;
otherwise overwrite / append to existion definitions
-t: assume text format; either "size" must be given or the
text data must be '\0' terminated
-b: assume binary format ('\0' separated, "\0\0" terminated)
-c: assume checksum protected environment format
addr: memory address to read from
size: length of input data; if missing, proper '\0'
termination is mandatory

- env default -f

reset default environment: drop all environment settings and load default environment

- env ask name [message] [size]

same as "askenv": ask for environment variable

- env edit name

same as "editenv": edit environment variable

- env run

same as "run": run commands in an environment variable

======================================================================

TODO:

- drop default env as implemented now; provide a text file based initialization instead (eventually using several text files to incrementally build it from common blocks) and a tool to convert it into a binary blob / object file.

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

- Some boards don't link any more due to the grown code size:
AR405, CANBT, DU405, PMC440, canyonlands, sc3, sequoia, socrates.

=> cc: Matthias Fuchs <[email protected]>,
Stefan Roese <[email protected]>,
Heiko Schocher <[email protected]>

- Dropping forceenv() causes build problems on schmoogie

=> cc: Sergey Kubushyn <[email protected]>

- Build tested on PPC and ARM only; runtime tested with NOR and NAND flash only => needs testing!!

Cc Matthias Fuchs <[email protected]>,
Cc Stefan Roese <[email protected]>,
Cc Heiko Schocher <[email protected]>
Cc Sergey Kubushyn <[email protected]>
---
 README                 |    8 +
 board/zeus/zeus.c      |   25 +--
 common/cmd_nvedit.c    |  655 +++++++++++++++++++++++++++++++++---------------
 common/command.c       |    3 +-
 common/dlmalloc.c      |   25 +-
 common/env_common.c    |  125 +++++-----
 common/env_dataflash.c |  114 ++++++----
 common/env_eeprom.c    |   85 ++++---
 common/env_flash.c     |  245 ++++++++++---------
 common/env_mgdisk.c    |   33 +--
 common/env_nand.c      |  188 ++++++++------
 common/env_nowhere.c   |   11 +-
 common/env_nvram.c     |   46 +++-
 common/env_onenand.c   |   65 +++---
 common/env_sf.c        |  132 ++++++-----
 common/exports.c       |    1 -
 include/environment.h  |    5 +-
 lib/hashtable.c        |   32 ++-
 18 files changed, 1094 insertions(+), 704 deletions(-)
README +8 -0
index a9c98f2..3a3c631 100644
@@ -2354,6 +2354,14 @@ Configuration Settings:
 		on high Ethernet traffic.
 		Defaults to 4 if not defined.
 
+- CONFIG_ENV_MAX_ENTRIES
+
+        Maximum number of entries in the hash table that is used
+        internally to store the environment settings. The default
+        setting is supposed to be generous and should work in most
+        cases. This setting can be used to tune behaviour; see
+        lib/hashtable.c for details.
+
 The following definitions that deal with the placement and management
 of environment data (variable area); in general, we support the
 following configurations:
board/zeus/zeus.c +5 -20
index e295151..4e6878a 100644
@@ -222,27 +222,8 @@ static int restore_default(void)
 	char *buf_save;
 	u32 crc;
 
-	/*
-	 * Unprotect and erase environment area
-	 */
-	flash_protect(FLAG_PROTECT_CLEAR,
-		      CONFIG_ENV_ADDR_REDUND,
-		      CONFIG_ENV_ADDR_REDUND + 2*CONFIG_ENV_SECT_SIZE - 1,
-		      &flash_info[0]);
+	set_default_env("");
 
-	flash_sect_erase(CONFIG_ENV_ADDR_REDUND,
-			 CONFIG_ENV_ADDR_REDUND + 2*CONFIG_ENV_SECT_SIZE - 1);
-
-	/*
-	 * Now restore default environment from U-Boot image
-	 * -> ipaddr, serverip...
-	 */
-	memset(env_ptr, 0, sizeof(env_t));
-	memcpy(env_ptr->data, default_environment, ENV_SIZE);
-#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
-	env_ptr->flags = 0xFF;
-#endif
-	env_crc_update();
 	gd->env_valid = 1;
 
 	/*
@@ -251,6 +232,10 @@ static int restore_default(void)
 	 * -> ethaddr, eth1addr, serial#
 	 */
 	buf = buf_save = malloc(FACTORY_RESET_ENV_SIZE);
+	if (buf == NULL) {
+		printf("ERROR: malloc() failed\n");
+		return -1;
+	}
 	if (eeprom_read(FACTORY_RESET_I2C_EEPROM, FACTORY_RESET_ENV_OFFS,
 			(u8 *)buf, FACTORY_RESET_ENV_SIZE)) {
 		puts("\nError reading EEPROM!\n");
common/cmd_nvedit.c +458 -197

921 lines not on this page · raw message

common/command.c +2 -1
index a1fc592..b12a278 100644
@@ -160,6 +160,7 @@ int cmd_usage(cmd_tbl_t *cmdtp)
 
 int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[])
 {
+#if 0 /* need to reimplement */
 	static char tmp_buf[512];
 	int space;
 
@@ -170,7 +171,7 @@ int var_complete(int argc, char * const argv[], char last_char, int maxv, char *
 
 	if (!space && argc == 2)
 		return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf);
-
+#endif
 	return 0;
 }
 
common/dlmalloc.c +11 -14
index 2276532..ae5702d 100644
@@ -222,7 +222,6 @@
 
 
 
-
 /* Preliminaries */
 
 #ifndef __STD_C
@@ -935,10 +934,10 @@ struct mallinfo mALLINFo();
 #endif
 
 /* ---------- To make a malloc.h, end cutting here ------------ */
-#else				/* Moved to malloc.h */
+#endif	/* 0 */			/* Moved to malloc.h */
 
 #include <malloc.h>
-#if 0
+#ifdef DEBUG
 #if __STD_C
 static void malloc_update_mallinfo (void);
 void malloc_stats (void);
@@ -946,9 +945,7 @@ void malloc_stats (void);
 static void malloc_update_mallinfo ();
 void malloc_stats();
 #endif
-#endif	/* 0 */
-
-#endif	/* 0 */			/* Moved to malloc.h */
+#endif	/* DEBUG */
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -1618,9 +1615,9 @@ static struct mallinfo current_mallinfo = {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
 /* Tracking mmaps */
 
-#if 0
+#ifdef DEBUG
 static unsigned int n_mmaps = 0;
-#endif	/* 0 */
+#endif	/* DEBUG */
 static unsigned long mmapped_mem = 0;
 #if HAVE_MMAP
 static unsigned int max_n_mmaps = 0;
@@ -3101,7 +3098,7 @@ size_t malloc_usable_size(mem) Void_t* mem;
 
 /* Utility to update current_mallinfo for malloc_stats and mallinfo() */
 
-#if 0
+#ifdef DEBUG
 static void malloc_update_mallinfo()
 {
   int i;
@@ -3139,7 +3136,7 @@ static void malloc_update_mallinfo()
   current_mallinfo.keepcost = chunksize(top);
 
 }
-#endif	/* 0 */
+#endif	/* DEBUG */
 
 
 
@@ -3158,7 +3155,7 @@ static void malloc_update_mallinfo()
 
 */
 
-#if 0
+#ifdef DEBUG
 void malloc_stats()
 {
   malloc_update_mallinfo();
@@ -3173,19 +3170,19 @@ void malloc_stats()
 	  (unsigned int)max_n_mmaps);
 #endif
 }
-#endif	/* 0 */
+#endif	/* DEBUG */
 
 /*
   mallinfo returns a copy of updated current mallinfo.
 */
 
-#if 0
+#ifdef DEBUG
 struct mallinfo mALLINFo()
 {
   malloc_update_mallinfo();
   return current_mallinfo;
 }
-#endif	/* 0 */
+#endif	/* DEBUG */
 
 
 
common/env_common.c +60 -65

190 lines not on this page · raw message

common/env_dataflash.c +71 -43

157 lines not on this page · raw message

common/env_eeprom.c +55 -30

226 lines not on this page · raw message

common/env_flash.c +131 -114

395 lines not on this page · raw message

common/env_mgdisk.c +13 -20
index b9de1ed..a69923b 100644
@@ -30,7 +30,7 @@
 /* references to names in env_common.c */
 extern uchar default_environment[];
 
-char * env_name_spec = "MG_DISK";
+char *env_name_spec = "MG_DISK";
 
 env_t *env_ptr = 0;
 
@@ -38,34 +38,27 @@ DECLARE_GLOBAL_DATA_PTR;
 
 uchar env_get_char_spec(int index)
 {
-	return (*((uchar *) (gd->env_addr + index)));
+	return (*((uchar *)(gd->env_addr + index)));
 }
 
 void env_relocate_spec(void)
 {
-	unsigned int err;
+	char buf[CONFIG_ENV_SIZE];
+	unsigned int err, rc;
 
 	err = mg_disk_init();
 	if (err) {
-		puts ("*** Warning - mg_disk_init error");
-		goto OUT;
-	}
-	err = mg_disk_read(CONFIG_ENV_ADDR, (u_char *)env_ptr, CONFIG_ENV_SIZE);
-	if (err) {
-		puts ("*** Warning - mg_disk_read error");
-		goto OUT;
+		set_default_env("!mg_disk_init error");
+		return;
 	}
 
-	if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) {
-		puts ("*** Warning - CRC error");
-		goto OUT;
+	err = mg_disk_read(CONFIG_ENV_ADDR, buf, CONFIG_ENV_SIZE);
+	if (err) {
+		set_default_env("!mg_disk_read error");
+		return;
 	}
 
-	return;
-
-OUT:
-	printf (", using default environment\n\n");
-	set_default_env();
+	env_import(buf, 1);
 }
 
 int saveenv(void)
@@ -76,7 +69,7 @@ int saveenv(void)
 	err = mg_disk_write(CONFIG_ENV_ADDR, (u_char *)env_ptr,
 			CONFIG_ENV_SIZE);
 	if (err)
-		puts ("*** Warning - mg_disk_write error\n\n");
+		puts("*** Warning - mg_disk_write error\n\n");
 
 	return err;
 }
@@ -84,7 +77,7 @@ int saveenv(void)
 int env_init(void)
 {
 	/* use default */
-	gd->env_addr = (ulong) & default_environment[0];
+	gd->env_addr = (ulong)&default_environment[0];
 	gd->env_valid = 1;
 
 	return 0;
common/env_nand.c +107 -81

341 lines not on this page · raw message

common/env_nowhere.c +5 -6
index ccc068b..75ef78d 100644
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000-2002
+ * (C) Copyright 2000-2010
  * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
  *
  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
@@ -35,22 +35,21 @@ env_t *env_ptr = NULL;
 
 extern uchar default_environment[];
 
-
-void env_relocate_spec (void)
+void env_relocate_spec(void)
 {
 }
 
-uchar env_get_char_spec (int index)
+uchar env_get_char_spec(int index)
 {
 	return ( *((uchar *)(gd->env_addr + index)) );
 }
 
-/************************************************************************
+/*
  * Initialize Environment use
  *
  * We are still running from ROM, so data use is limited
  */
-int  env_init(void)
+int env_init(void)
 {
 	gd->env_addr  = (ulong)&default_environment[0];
 	gd->env_valid = 0;
common/env_nvram.c +32 -14

90 lines not on this page · raw message

common/env_onenand.c +36 -29

122 lines not on this page · raw message

common/env_sf.c +73 -59

266 lines not on this page · raw message

common/exports.c +0 -1
index bde52a6..3dff735 100644
@@ -6,7 +6,6 @@ DECLARE_GLOBAL_DATA_PTR;
 __attribute__((unused)) static void dummy(void)
 {
 }
-#endif
 
 unsigned long get_version(void)
 {
include/environment.h +4 -1
index fbccf6a..bedbc54 100644
@@ -160,6 +160,9 @@ unsigned char env_get_char_memory (int index);
 void env_crc_update (void);
 
 /* [re]set to the default environment */
-void set_default_env(void);
+void set_default_env(const char *s);
+
+/* Import from binary representation into hash table */
+int env_import(const char *buf, int check);
 
 #endif	/* _ENVIRONMENT_H_ */
lib/hashtable.c +23 -9
index 2f3b5c8..c573992 100644
@@ -45,6 +45,10 @@
 # include <linux/string.h>
 #endif
 
+#ifndef	CONFIG_ENV_MAX_ENTRIES	/* maximum number of entries */
+#define	CONFIG_ENV_MAX_ENTRIES 512
+#endif
+
 #include "search.h"
 
 /*
@@ -636,15 +640,23 @@ int himport_r(struct hsearch_data *htab,
 	 * table size is based on heuristics: in a sample of some 70+
 	 * existing systems we found an average size of 39+ bytes per entry
 	 * in the environment (for the whole key=value pair). Assuming a
-	 * size of 7 per entry (= safety factor of >5) should provide enough
-	 * safety margin for any existing environment definitons and still
+	 * size of 8 per entry (= safety factor of ~5) should provide enough
+	 * safety margin for any existing environment definitions and still
 	 * allow for more than enough dynamic additions. Note that the
 	 * "size" argument is supposed to give the maximum enviroment size
-	 * (CONFIG_ENV_SIZE).
+	 * (CONFIG_ENV_SIZE).  This heuristics will result in
+	 * unreasonably large numbers (and thus memory footprint) for
[… more lines in the raw message]

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.1.1

Part of the diff is not shown here. View the raw message.

#18 lore raw

PATCH 1/1 new env: fix off-by-one error in setenv command

Fix an off-by-one error in the string concatenation for the setevn command which would write over the end of the allocated area, resulting eventually in a crash due to corruption of the malloc metadata.

---
Posted as incremental patch here to provide quick fix to testers (also pushed to "hashtable" branch in u-boot-testing repo. Will be squashed into new env code patch when resubmitting.

 common/cmd_nvedit.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
common/cmd_nvedit.c +2 -2
index 976a30b..010d003 100644
@@ -273,7 +273,7 @@ int _do_env_set (int flag, int argc, char * const argv[])
 	/*
 	 * Insert / replace new value
 	 */
-	for (i=2,len=1; i<argc; ++i) {
+	for (i=2,len=0; i<argc; ++i) {
 		len += strlen(argv[i]) + 1;
 	}
 	if ((value = malloc(len)) == NULL) {
@@ -285,7 +285,7 @@ int _do_env_set (int flag, int argc, char * const argv[])
 
 		while ((*s++ = *v++) != '\0')
 			;
-		*s++ = ' ';
+		*(s-1) = ' ';
 	}
 	if (s != value)
 		*--s = '\0';
Signature · 1 line
1.7.1.1
#19 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

In reply to Wolfgang Denk
Quoted 4 lines · On Sat, 17 Jul 2010 21:45:48 +0200 Wolfgang Denk <[email protected]> wrote:

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

you were right - a grepenv/findenv/'env search' substring implementation on top of this looks to be at least as expensive as a full export operation :/

Quoted 3 lines

int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]) {
+#if 0 /* need to reimplement */

ouch - this is u-boot's most useful feature :)

It would be good to know boot time overhead the initial import function makes, esp. in terms of number of boot-time accesses to the environment...

Kim

#20 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Kim Phillips,

Quoted 9 lines · In message <[email protected]> you wrote:
Quoted 5 lines

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

you were right - a grepenv/findenv/'env search' substring implementation on top of this looks to be at least as expensive as a full export operation :/

Expensive in terms of what? Code size? Probably not. It all boils down to running strstr() over all entries...

Quoted 5 lines
Quoted 3 lines

int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]) {
+#if 0 /* need to reimplement */

ouch - this is u-boot's most useful feature :)

He. We should probably run a poll for UMUF :-)

Quoted 3 lines

It would be good to know boot time overhead the initial import function makes, esp. in terms of number of boot-time accesses to the environment...

I don't see any significant changes on the systems I tested...

Example TQM5200:

MPC5200 at 400 MHz, 16 KiB environment size, ~2 KiB used:

relevant env settings:

nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}
addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1 addcons=setenv bootargs ${bootargs} console=${console},${baudrate}
net_nfs=tftp ${kernel_addr_r} ${bootfile}; tftp ${fdt_addr_r} ${fdt_file}; run nfsargs addip addcons; bootm ${kernel_addr_r} - ${fdt_addr_r} bootcmd=run net_nfs

old: U-Boot 2010.03-00167-g6e5fb4e (Apr 27 2010 - 15:37:15)
new: U-Boot 2010.06-00208-g7151bce-dirty (Jul 18 2010 - 00:36:48)

   old   new
 0.000   0.000 U-Boot 2010.03-00167-g6e5fb4e (Apr 27 2010 - 15:37:15)   
 0.000   0.000  
 0.000   0.000 CPU:   MPC5200B v2.2, Core v1.4 at 396 MHz  
 0.000   0.000        Bus 132 MHz, IPB 132 MHz, PCI 66 MHz  
 0.040   0.040 Board: TQM5200S (TQ-Components GmbH)  
 0.040   0.040        on a STK52xx carrier board  
 0.040   0.040 I2C:   85 kHz, ready  
 0.040   0.040 DRAM:  64 MB  
 0.080   0.080 FLASH: 32 MB  
 0.120   0.130 In:    serial  
 0.120   0.130 Out:   serial  
 0.120   0.130 Err:   serial  
 0.160   0.130 Net:   FEC ETHERNET  
 0.420   0.400 POST i2c PASSED  
 0.440   0.440 POST cpu PASSED  
 0.920   0.920 IDE:   Bus 0: OK   
 0.920   0.920   Device 0: Model: HITACHI_DK23DA-20 Firm: 00J2A0A1 Ser#: 12Y0MN  
 0.920   0.920             Type: Hard Disk  
 0.920   0.920             Capacity: 19077.1 MB = 18.6 GB (39070080 x 512)  
 2.840   2.871   Device 1: not available  
 2.840   2.871 SRAM:  512 kB  
 4.840   4.860 PS/2:  No device found  
 5.840   5.880 Kbd:   reset failed, no ACK  
 5.880   5.880
 5.880   5.880 Type run flash_nfs to mount root filesystem over NFS   
 5.880   5.880
10.880  10.880 Hit any key to stop autoboot:  0   
12.520  12.480 Using FEC ETHERNET device  
...
13.480  13.361 Bytes transferred = 7275 (1c6b hex)  
13.640  13.400 ## Booting kernel from Legacy Image at 00400000 ...  
13.640  13.400    Image Name:   Linux-2.6.32-rc5-01449-g2c33dca  
...
13.960  13.720 ## Flattened Device Tree blob at 00600000  
13.960  13.720    Booting using the fdt blob at 0x600000  
14.960  13.720    Uncompressing Kernel Image ... OK  
15.040  14.760 [    0.000000] Using mpc5200-simple-platform machine description  
15.040  14.760 [    0.000000] Linux version 2.6.32-rc5-01449-g2c33dca (wd at pollux.denx.de) (gcc version 4.2.2) #1 Mon Nov 2 09:31:00 CET 2009  

...

As you can see, there are stages where the new code is a bit slower (20...40 milliseconds, which is close to the resolution of the measurement), but in this specific test we win some 280 milliseconds; if you exclude the 5 seconds boot delay that's some 2.7%. I don't think it's worth mentioning, but at least it's not worse than the old code.

I haven't tested many boards, especially not for timing. If you have additional input it will be welcome.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"If you own a machine, you are in turn owned by it,  and  spend  your
time serving it..."    - Marion Zimmer Bradley, _The Forbidden Tower_
#21 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Quoted 9 lines · On Tue, 20 Jul 2010 11:40:23 +0200 Wolfgang Denk <[email protected]> wrote:

Dear Kim Phillips,

Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 5 lines

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

Quoted 6 lines
Quoted 3 lines

you were right - a grepenv/findenv/'env search' substring implementation on top of this looks to be at least as expensive as a full export operation :/

Expensive in terms of what? Code size? Probably not. It all boils down to running strstr() over all entries...

time I thought, but ok, I'll look into it when I have time.

Quoted 6 lines

As you can see, there are stages where the new code is a bit slower (20...40 milliseconds, which is close to the resolution of the measurement), but in this specific test we win some 280 milliseconds; if you exclude the 5 seconds boot delay that's some 2.7%. I don't think it's worth mentioning, but at least it's not worse than the old code.

excellent, thank you.

Quoted 2 lines

I haven't tested many boards, especially not for timing. If you have additional input it will be welcome.

I would, however u-boot-testing.git/hashtable currently fails to boot on an 8572:

U-Boot 2010.06-02552-g9895ea5 (Jul 19 2010 - 18:39:19)

CPU0:  8572E, Version: 1.1, (0x80e80011)
Core:  E500, Version: 3.0, (0x80210030)
Clock Configuration:
       CPU0:1499.985 MHz, CPU1:1499.985 MHz, 
       CCB:599.994 MHz,
       DDR:399.996 MHz (799.992 MT/s data rate) (Asynchronous), LBC:37.500 MHz
L1:    D-cache 32 kB enabled
       I-cache 32 kB enabled
Board: MPC8572DS Sys ID: 0x14, Sys Ver: 0x30, FPGA Ver: 0x10, vBank: 0
I2C:   ready
DRAM:  Initializing....

I presume it's related to the issue brought up in this thread?:

http://lists.denx.de/pipermail/u-boot/2010-July/074151.html

Cheers,

Kim

#22 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Kim Phillips,

Quoted 3 lines · In message <[email protected]> you wrote:

I would, however u-boot-testing.git/hashtable currently fails to boot on an 8572:

Hm... one of the boards I don't have access to; can you please help debug the problem?

Quoted 14 lines

U-Boot 2010.06-02552-g9895ea5 (Jul 19 2010 - 18:39:19)

CPU0:  8572E, Version: 1.1, (0x80e80011)
Core:  E500, Version: 3.0, (0x80210030)
Clock Configuration:
       CPU0:1499.985 MHz, CPU1:1499.985 MHz, 
       CCB:599.994 MHz,
       DDR:399.996 MHz (799.992 MT/s data rate) (Asynchronous), LBC:37.500 MHz
L1:    D-cache 32 kB enabled
       I-cache 32 kB enabled
Board: MPC8572DS Sys ID: 0x14, Sys Ver: 0x30, FPGA Ver: 0x10, vBank: 0
I2C:   ready
DRAM:  Initializing....
Quoted 3 lines

I presume it's related to the issue brought up in this thread?:

http://lists.denx.de/pipermail/u-boot/2010-July/074151.html

Hm... I don't think so, but as it's failing there must be some bug somewhere... My thinking is that all the relevant environment handling that actually uses errno is related to the hash table handling, and all this runs definitely only after relocation to RAM, so this should not be the problem.

What we see here is in the pre-relocation phase, where we are still parsing the original, in-flash copy of the stringified environment. What is strange is that this seems to have worked when accessing "baudrate" (either because the environment was found, or because the default environment was used), but is stopping here.

Can you attach a debugger and check?

Best regards,

Wolfgang Denk

Signature · 8 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"The net result is a system that is not only binary  compatible  with
4.3  BSD, but is even bug for bug compatible in almost all features."
- Avadit  Tevanian,  Jr.,  "Architecture-Independent  Virtual  Memory
Management  for  Parallel  and  Distributed  Environments:  The  Mach
Approach"
#23 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Kim,

Quoted 6 lines · In message <[email protected]> I wrote:

What we see here is in the pre-relocation phase, where we are still parsing the original, in-flash copy of the stringified environment. What is strange is that this seems to have worked when accessing "baudrate" (either because the environment was found, or because the default environment was used), but is stopping here.

I think the problem is that before relocation we have to use getenv_r(), which is done for example to read the baudrate, see arch/powerpc/lib/board.c: init_baudrate()

However, some boards also use getenv() before relocation. I just found for example that the Sequoia board does this (before relocation):

"board/amcc/sequoia/sequoia.c":

330 int checkboard(void)
331 {

332         char *s = getenv("serial#");
333         u8 rev;
334         u32 clock = get_async_pci_freq();

335
336 #ifdef CONFIG_440EPX
337 printf("Board: Sequoia - AMCC PPC440EPx Evaluation Board");
338 #else
339 printf("Board: Rainier - AMCC PPC440GRx Evaluation Board");
340 #endif
...

and as one can expect the board crashes before printing the board information.

I'm considering a way to eliminate getenv_r() (at the cost of providing some static buffer in the global data area?).

[Comments? Ideas?]

However, I cannot see any gentenv() use before relocation for your board, so the problem there is still unclear. I think I need your help to debug this...

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Human beings were created by water to transport it uphill.

A message that is not in the archive (sent off-list or not yet received): 1279658019.5685.125.camel@thunk

#25 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Peter,

Quoted 8 lines · In message <1279658019.5685.125.camel@thunk> you wrote:
Quoted 4 lines

I think the problem is that before relocation we have to use getenv_r(), which is done for example to read the baudrate, see arch/powerpc/lib/board.c: init_baudrate()

How hard is it to detect this case and generate a stackdump if someone calls getenv() before relocation is complete? That would help to spot places where people are breaking the rules...

It's trivial to check - all we need to addd to getenv() is something like

	if (!(gd->flags & GD_FLG_RELOC))
		bail_out();

But then, we could as well try to be friendly and eliminate getenv_r(). We would just need a static buffer for the result.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Reader, suppose you were an idiot. And suppose you were a  member  of
Congress. But I repeat myself.                           - Mark Twain
#26 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

In reply to Wolfgang Denk
Quoted 3 lines · On Tue, 20 Jul 2010 22:09:08 +0200 Wolfgang Denk <[email protected]> wrote:

However, I cannot see any gentenv() use before relocation for your board, so the problem there is still unclear. I think I need your help to debug this...

looks like arch/powerpc/cpu/mpc8xxx/ddr/options.c gets memory interleaving configuration from the environment, using getenv().

Kim

#27 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Kim,

Quoted 7 lines · In message <[email protected]> you wrote:
Quoted 4 lines

However, I cannot see any gentenv() use before relocation for your board, so the problem there is still unclear. I think I need your help to debug this...

looks like arch/powerpc/cpu/mpc8xxx/ddr/options.c gets memory interleaving configuration from the environment, using getenv().

Ah! Can you please try the following patch - it's not intended to be a fix, just to verify my hypothesis. Thanks in advance.

arch/powerpc/cpu/mpc8xxx/ddr/options.c +15 -12
index 46731c8..0b9cb1d 100644
@@ -24,6 +24,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 {
 	unsigned int i;
 	const char *p;
+	char tmp[64];
 
 	/* Chip select options. */
 
@@ -221,7 +222,8 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 	 * should be a subset of the requested configuration.
 	 */
 #if (CONFIG_NUM_DDR_CONTROLLERS > 1)
-	if ((p = getenv("memctl_intlv_ctl")) != NULL) {
+	i = getenv_r("memctl_intlv_ctl", tmp, sizeof (tmp));
+	if (i > 0) {
 		if (pdimm[0].n_ranks == 0) {
 			printf("There is no rank on CS0. Because only rank on "
 				"CS0 and ranks chip-select interleaved with CS0"
@@ -230,37 +232,38 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 			popts->memctl_interleaving = 0;
 		} else {
 			popts->memctl_interleaving = 1;
-			if (strcmp(p, "cacheline") == 0)
+			if (strcmp(tmp, "cacheline") == 0)
 				popts->memctl_interleaving_mode =
 					FSL_DDR_CACHE_LINE_INTERLEAVING;
-			else if (strcmp(p, "page") == 0)
+			else if (strcmp(tmp, "page") == 0)
 				popts->memctl_interleaving_mode =
 					FSL_DDR_PAGE_INTERLEAVING;
-			else if (strcmp(p, "bank") == 0)
+			else if (strcmp(tmp, "bank") == 0)
 				popts->memctl_interleaving_mode =
 					FSL_DDR_BANK_INTERLEAVING;
-			else if (strcmp(p, "superbank") == 0)
+			else if (strcmp(tmp, "superbank") == 0)
 				popts->memctl_interleaving_mode =
 					FSL_DDR_SUPERBANK_INTERLEAVING;
 			else
 				popts->memctl_interleaving_mode =
-						simple_strtoul(p, NULL, 0);
+						simple_strtoul(tmp, NULL, 0);
 		}
 	}
 #endif
 
-	if( ((p = getenv("ba_intlv_ctl")) != NULL) &&
+	i = getenv_r("ba_intlv_ctl", tmp, sizeof (tmp));
+	if (i > 0) && (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
 		(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
-		if (strcmp(p, "cs0_cs1") == 0)
+		if (strcmp(tmp, "cs0_cs1") == 0)
 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
-		else if (strcmp(p, "cs2_cs3") == 0)
+		else if (strcmp(tmp, "cs2_cs3") == 0)
 			popts->ba_intlv_ctl = FSL_DDR_CS2_CS3;
-		else if (strcmp(p, "cs0_cs1_and_cs2_cs3") == 0)
+		else if (strcmp(tmp, "cs0_cs1_and_cs2_cs3") == 0)
 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_AND_CS2_CS3;
-		else if (strcmp(p, "cs0_cs1_cs2_cs3") == 0)
+		else if (strcmp(tmp, "cs0_cs1_cs2_cs3") == 0)
 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1_CS2_CS3;
 		else
-			popts->ba_intlv_ctl = simple_strtoul(p, NULL, 0);
+			popts->ba_intlv_ctl = simple_strtoul(tmp, NULL, 0);
 
 		switch (popts->ba_intlv_ctl & FSL_DDR_CS0_CS1_CS2_CS3) {
 		case FSL_DDR_CS0_CS1_CS2_CS3:

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"In Christianity neither morality nor religion come into contact with
reality at any point."                          - Friedrich Nietzsche
#28 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Quoted 8 lines · On Tue, 20 Jul 2010 23:43:14 +0200 Wolfgang Denk <[email protected]> wrote:

Dear Kim,

Quoted 5 lines · In message <[email protected]> you wrote:
Quoted 4 lines

However, I cannot see any gentenv() use before relocation for your board, so the problem there is still unclear. I think I need your help to debug this...

Quoted 5 lines
Quoted 2 lines

looks like arch/powerpc/cpu/mpc8xxx/ddr/options.c gets memory interleaving configuration from the environment, using getenv().

Ah! Can you please try the following patch - it's not intended to be a fix, just to verify my hypothesis. Thanks in advance.

indeed, your patch plus the following makes the 8572 boot properly again.

arch/powerpc/cpu/mpc8xxx/ddr/options.c +1 -2
index 0b9cb1d..692669f 100644
@@ -252,8 +252,7 @@ unsigned int populate_memctl_options(int all_DIMMs_registered,
 #endif
 
 	i = getenv_r("ba_intlv_ctl", tmp, sizeof (tmp));
-	if (i > 0) && (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
-		(CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
+	if ((i > 0) && (CONFIG_CHIP_SELECTS_PER_CTRL > 1)) {
 		if (strcmp(tmp, "cs0_cs1") == 0)
 			popts->ba_intlv_ctl = FSL_DDR_CS0_CS1;
 		else if (strcmp(tmp, "cs2_cs3") == 0)

Kim

#29 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Kim,

Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 3 lines

Ah! Can you please try the following patch - it's not intended to be a fix, just to verify my hypothesis. Thanks in advance.

indeed, your patch plus the following makes the 8572 boot properly again.

Thanks for testing.

Could you please also test the code from the current (rebased) version in the "hashtable" branch of the git://git.denx.de/u-boot-testing.git
repo?

I have adresses the problem of early environment accesses, and at least on the boards I've tested so far it appears to be working.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I will not say that women have no character;  rather, they have a new
one every day.                                               -- Heine
#30 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Quoted 6 lines · On Sun, 25 Jul 2010 23:45:02 +0200 Wolfgang Denk <[email protected]> wrote:

Could you please also test the code from the current (rebased) version in the "hashtable" branch of the git://git.denx.de/u-boot-testing.git
repo?

I have adresses the problem of early environment accesses, and at least on the boards I've tested so far it appears to be working.

U-Boot 2010.06-02590-g38045a3 ("4xx: Make sequoia board build with new environment code") runs beautifully on the 8572.

Thanks,

Kim

#31 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

In reply to Kim Phillips

Dear Kim Phillips,

Quoted 3 lines · In message <[email protected]> you wrote:

I would, however u-boot-testing.git/hashtable currently fails to boot on an 8572:

...

Quoted 3 lines

I presume it's related to the issue brought up in this thread?:

http://lists.denx.de/pipermail/u-boot/2010-July/074151.html

I smell a wumpus. Don't spend time on debugging this, let me track down an idea first, please.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
What the gods would destroy they first submit to  an  IEEE  standards
committee.
#32 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

In reply to Wolfgang Denk

Hi Wolfgang,

I could think of some situations where the new env command is helpful. But more during development than for production systems.

Switching between environment profiles would be cool. And a "env default -f" behavior that keeps MAC addresses and serial# is also on my wishlist.

I did some testing on our PMC440 with environment in EEPROM. Please see some comments below.

Quoted 4 lines · Wolfgang Denk
common/cmd_nvedit.c +0 -0
index 8c86f15..976a30b 100644

...

Quoted 14 lines

+/*
+ * env export [-t | -b | -c] addr [size]
+ * -t: export as text format; if size is given, data will be
+ * padded with '\0' bytes; if not, one terminating '\0'
+ * will be added (which is included in the "filesize"
+ * setting so you can for exmple copy this to flash and
+ * keep the termination).
+ * -b: export as binary format (name=value pairs separated by
+ * '\0', list end marked by double "\0\0")
+ * -c: export as checksum protected environment format as
+ * used for example by "saveenv" command
+ * addr: memory address where environment gets stored
+ * size: size of output buffer
+ *

...

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 597

Quoted 7 lines
common/cmd_nvedit.c +7 -0
+static int do_env_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char	buf[32];
+	char	*addr, *cmd, *res;
+	size_t	size;
+	ssize_t	len;
+	env_t	*envp = (env_t *)addr;

addr is uninitialized. declaration is enough here.

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 604

Quoted 7 lines
common/cmd_nvedit.c +7 -0
+	char	sep = '\n';
+	int	chk = 0;
+	int	fmt = 0;
+
+	cmd = *argv;
+
+	while (--argc > 0 && **++argv == '-') {

I'd like some more braces for readability.

Quoted 45 lines
common/cmd_nvedit.c +43 -1
+		char *arg = *argv;
+		while (*++arg) {
+			switch (*arg) {
+			case 'b':		/* raw binary format */
+				if (fmt++)
+					goto sep_err;
+				sep = '\0';
+				break;
+			case 'c':		/* external checksum format */
+				if (fmt++)
+					goto sep_err;
+				sep = '\0';
+				chk = 1;
+				break;
+			case 't':		/* text format */
+				if (fmt++)
+					goto sep_err;
+				sep = '\n';
+				break;
+			default:
+				cmd_usage(cmdtp);
+				return 1;
+			}
+		}
+	}
 
-/**************************************************/
+	if (argc < 1) {
+		cmd_usage(cmdtp);
+		return 1;
+	}
+
+	addr = (char *)simple_strtoul(argv[0], NULL, 16);
+
+	if (argc == 2) {
+		size = simple_strtoul(argv[1], NULL, 16);
+		memset(addr, '\0', size);
+	} else {
+		size = 0;
+	}
+
+	if (sep) {		/* export as text file */
+		len = hexport(sep, &addr, size);
+		if (len < 0) {
+			error("Cannot export environment: errno = %d\n",

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 658

Quoted 10 lines
common/cmd_nvedit.c +10 -0
+				errno);
+			return 1;
+		}
+		sprintf(buf, "%zX", len);
+		setenv("filesize", buf);
+
+		return 0;
+	}
+
+	if (chk) {		/* export as checksum protected block */

Add:

		envp = (env_t *)addr;

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 661

Quoted 3 lines
common/cmd_nvedit.c +3 -0
+		res = (char *)&envp->data;
+	} else {		/* export as raw binary data */
+		res = (char *)&addr;

Should'n this be

		res = addr;
Quoted 16 lines
common/cmd_nvedit.c +16 -0
+	}
+
+	len = hexport('\0', &res, ENV_SIZE);
+	if (len < 0) {
+		error("Cannot export environment: errno = %d\n",
+			errno);
+		return 1;
+	}
+
+	if (chk) {
+		envp->crc   = crc32(0, envp->data, ENV_SIZE);
+#ifdef CONFIG_ENV_ADDR_REDUND
+		envp->flags = ACTIVE_FLAG;
+#endif
+	}
+	sprintf(buf, "%zX", len + offsetof(env_t,data));

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 687

Quoted 10 lines
common/cmd_nvedit.c +10 -0
+	setenv("filesize", buf);
+
+	return 0;
+
+sep_err:
+	printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
+		cmd);
+	return 1;
+}
+

...

Fixes for non-building board (AR405, CANBT, PMC440) will come up shortly.

Matthias

#33 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Matthias Fuchs,

Quoted 3 lines · In message <[email protected]> you wrote:

I could think of some situations where the new env command is helpful. But more during development than for production systems.

It depends. "Reset to factory defaults" is a not so uncommon request. And acceleration of scripts is not so uncommon either.

Quoted 2 lines

Switching between environment profiles would be cool. And a "env default -f" behavior that keeps MAC addresses and serial# is also on my wishlist.

Actually neither MAC addresses nor serial# are part of the default environment.

Quoted 2 lines

I did some testing on our PMC440 with environment in EEPROM. Please see some comments below.

Thanks.

Quoted 8 lines

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 597

Quoted 7 lines
common/cmd_nvedit.c +7 -0
+static int do_env_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char	buf[32];
+	char	*addr, *cmd, *res;
+	size_t	size;
+	ssize_t	len;
+	env_t	*envp = (env_t *)addr;

addr is uninitialized. declaration is enough here.

Will check this.

...

Quoted 8 lines

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 658

Quoted 1 line
common/cmd_nvedit.c +1 -0
+	if (chk) {		/* export as checksum protected block */

Add:

		envp = (env_t *)addr;

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 661

Quoted 3 lines
common/cmd_nvedit.c +3 -0
+		res = (char *)&envp->data;
+	} else {		/* export as raw binary data */
+		res = (char *)&addr;

Should'n this be

		res = addr;

No. We need the address of the pointer variable, so the function can store the result pointer there.

...

Quoted 1 line

Fixes for non-building board (AR405, CANBT, PMC440) will come up shortly.

Thanks a lot.

#34 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Hi Wolfgang,

Quoted 7 lines · Wolfgang Denk

Dear Matthias Fuchs,

Quoted 3 lines · In message <[email protected]> you wrote:

I could think of some situations where the new env command is helpful. But more during development than for production systems.

Quoted 8 lines

It depends. "Reset to factory defaults" is a not so uncommon request. And acceleration of scripts is not so uncommon either.

Quoted 2 lines

Switching between environment profiles would be cool. And a "env default -f" behavior that keeps MAC addresses and serial# is also on my wishlist.

Actually neither MAC addresses nor serial# are part of the default environment.

Right. But, I'd like to have that described feature in any case. Let's call it different, but the functionality would be helpful. What about a further option like '-p' for keep _p_rotected.

Quoted 21 lines
Quoted 3 lines

I did some testing on our PMC440 with environment in EEPROM. Please see some comments below.

Thanks.

Quoted 8 lines

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 597

Quoted 7 lines
common/cmd_nvedit.c +7 -0
+static int do_env_export(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char	buf[32];
+	char	*addr, *cmd, *res;
+	size_t	size;
+	ssize_t	len;
+	env_t	*envp = (env_t *)addr;

addr is uninitialized. declaration is enough here.

Will check this.

...

Quoted 3 lines

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 658

Quoted 1 line
common/cmd_nvedit.c +1 -0
+	if (chk) {		/* export as checksum protected block */

Add:

		envp = (env_t *)addr;
Quoted 8 lines
Quoted 5 lines

common/cmd_nvedit.c int envmatch (uchar *s1, int i2) · line 661

Quoted 3 lines
common/cmd_nvedit.c +3 -0
+		res = (char *)&envp->data;
+	} else {		/* export as raw binary data */
+		res = (char *)&addr;

Should'n this be

		res = addr;

No. We need the address of the pointer variable, so the function can store the result pointer there.

Nak. You added &-operator when calling: hexport('\0', &res, ENV_SIZE); That's one to much. You can also remove the &-operator from this:

		res = (char *)&envp->data;

So the code will look like this:

	if (chk) {		/* export as checksum protected block */
		envp = (env_t *)addr;
		res = (char *)envp->data;
	} else {		/* export as raw binary data */
		res = addr;
	}

	len = hexport('\0', &res, ENV_SIZE);

...

Matthias

#35 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

Dear Matthias Fuchs,

Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 3 lines

Actually neither MAC addresses nor serial# are part of the default environment.

Right. But, I'd like to have that described feature in any case. Let's call it different, but the functionality would be helpful. What about a further option like '-p' for keep _p_rotected.

I see this a s part of a sub-sequent patch (series), which adds flags to variables (like read-only, don't-save, etc.).

Quoted 7 lines
Quoted 2 lines

No. We need the address of the pointer variable, so the function can store the result pointer there.

Nak. You added &-operator when calling: hexport('\0', &res, ENV_SIZE); That's one to much. You can also remove the &-operator from this:

		res = (char *)&envp->data;

So the code will look like this:

Thanks, will re-check this when I have a little more time.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The more complex the mind, the greater the need for the simplicity of
play.
	-- Kirk, "Shore Leave", stardate 3025.8
author Applied
#36 lore raw

PATCH 5/5 New implementation for internal handling of environment variables.

In reply to Wolfgang Denk

Dear Wolfgang Denk,

Quoted 206 lines · In message <[email protected]> you wrote:

Motivation:

* Old environment code used a pessimizing implementation:
- variable lookup used linear search => slow
- changed/added variables were added at the end, i. e. most frequently used variables had the slowest access times => slow
- each setenv() would calculate the CRC32 checksum over the whole environment block => slow
* "redundant" envrionment was locked down to two copies
* No easy way to implement features like "reset to factory defaults", or to select one out of several pre-defined (previously saved) sets of environment settings ("profiles")
* No easy way to import or export environment settings

======================================================================

API Changes:

- Variable names starting with '#' are no longer allowed

I didn't find any such variable names being used; it is highly recommended to follow standard conventions and start variable names with an alphanumeric character

- "printenv" will now print a backslash at the end of all but the last lines of a multi-line variable value.

Multi-line variables have never been formally defined, allthough there is no reason not to use them. Now we define rules how to deal with them, allowing for import and export.

- Function forceenv() and the related code in saveenv() was removed. At the moment this is causing build problems for the only user of this code (schmoogie - which has no entry in MAINTAINERS); may be fixed later by implementing the "env set -f" feature.

Inconsistencies:

- "printenv" will '\\'-escape the '\n' in multi-line variables, while "printenv var" will not do that.

======================================================================

Advantages:

- "printenv" output much better readable (sorted)
- faster!
- extendable (additional variable properties can be added)
- new, powerful features like "factory reset" or easy switching between several different environment settings ("profiles")

Disadvantages:

- Image size grows by typically 5...7 KiB (might shrink a bit again on systems with redundant environment with a following patch series)

======================================================================

Implemented:

- env command with subcommands:

- env print [arg ...]

same as "printenv": print environment

- env set [-f] name [arg ...]

same as "setenv": set (and delete) environment variables

["-f" - force setting even for read-only variables - not implemented yet.]

- end delete [-f] name

not implemented yet

["-f" - force delete even for read-only variables]

- env save

same as "saveenv": save environment

- env export [-t | -b | -c] addr [size]

export internal representation (hash table) in formats usable for persistent storage or processing:

-t: export as text format; if size is given, data will be
padded with '\0' bytes; if not, one terminating '\0' will be added (which is included in the "filesize" setting so you can for exmple copy this to flash and keep the termination).
-b: export as binary format (name=value pairs separated by
'\0', list end marked by double "\0\0")
-c: export as checksum protected environment format as
used for example by "saveenv" command
addr: memory address where environment gets stored
size: size of output buffer

With "-c" and size is NOT given, then the export command will format the data as currently used for the persistent storage, i. e. it will use CONFIG_ENV_SECT_SIZE as output block size and prepend a valid CRC32 checksum and, in case of resundant environment, a "current" redundancy flag. If size is given, this value will be used instead of CONFIG_ENV_SECT_SIZE; again, CRC32 checksum and redundancy flag will be inserted.

With "-b" and "-t", always only the real data (including a terminating '\0' byte) will be written; here the optional size argument will be used to make sure not to overflow the user provided buffer; the command will abort if the size is not sufficient. Any remainign space will be '\0' padded.

On successful return, the variable "filesize" will be set. Note that filesize includes the trailing/terminating '\0' byte(s).

Usage szenario: create a text snapshot/backup of the current settings:

=> env export -t 100000
=> era ${backup_addr} +${filesize} => cp.b 100000 ${backup_addr} ${filesize}

Re-import this snapshot, deleting all other settings:

=> env import -d -t ${backup_addr}

- env import [-d] [-t | -b | -c] addr [size]

import external format (text or binary) into hash table, optionally deleting existing values:

-d: delete existing environment before importing;
otherwise overwrite / append to existion definitions
-t: assume text format; either "size" must be given or the
text data must be '\0' terminated
-b: assume binary format ('\0' separated, "\0\0" terminated)
-c: assume checksum protected environment format
addr: memory address to read from
size: length of input data; if missing, proper '\0'
termination is mandatory

- env default -f

reset default environment: drop all environment settings and load default environment

- env ask name [message] [size]

same as "askenv": ask for environment variable

- env edit name

same as "editenv": edit environment variable

- env run

same as "run": run commands in an environment variable

======================================================================

TODO:

- drop default env as implemented now; provide a text file based initialization instead (eventually using several text files to incrementally build it from common blocks) and a tool to convert it into a binary blob / object file.

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

- Some boards don't link any more due to the grown code size:
AR405, CANBT, DU405, PMC440, canyonlands, sc3, sequoia, socrates.

=> cc: Matthias Fuchs <[email protected]>,
Stefan Roese <[email protected]>,
Heiko Schocher <[email protected]>

- Dropping forceenv() causes build problems on schmoogie

=> cc: Sergey Kubushyn <[email protected]>

- Build tested on PPC and ARM only; runtime tested with NOR and NAND flash only => needs testing!!

Cc Matthias Fuchs <[email protected]>,
Cc Stefan Roese <[email protected]>,
Cc Heiko Schocher <[email protected]>
Cc Sergey Kubushyn <[email protected]>
---
 README                 |    8 +
 board/zeus/zeus.c      |   25 +--
 common/cmd_nvedit.c    |  655 +++++++++++++++++++++++++++++++++---------------
 common/command.c       |    3 +-
 common/dlmalloc.c      |   25 +-
 common/env_common.c    |  125 +++++-----
 common/env_dataflash.c |  114 ++++++----
 common/env_eeprom.c    |   85 ++++---
 common/env_flash.c     |  245 ++++++++++---------
 common/env_mgdisk.c    |   33 +--
 common/env_nand.c      |  188 ++++++++------
Quoted 8 lines
 common/env_nowhere.c   |   11 +-
 common/env_nvram.c     |   46 +++-
 common/env_onenand.c   |   65 +++---
 common/env_sf.c        |  132 ++++++-----
 common/exports.c       |    1 -
 include/environment.h  |    5 +-
 lib/hashtable.c        |   32 ++-
 18 files changed, 1094 insertions(+), 704 deletions(-)

Applied to "next" branch.

[With changes as suggested by Matthias Fuchs - thanks!]

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
What is tolerance? -- it is the consequence of humanity. We  are  all
formed  of frailty and error; let us pardon reciprocally each other's
folly -- that is the first law of nature.                  - Voltaire
#37 lore raw

[U-Boot] env_flash.c:saveenv() broken when env is smaller than a sector

In reply to Wolfgang Denk
Quoted 269 lines · On Saturday, July 17, 2010 15:45:48 Wolfgang Denk wrote:
common/env_flash.c +49 -55
 #ifdef CMD_SAVEENV
 int saveenv(void)
 {
-	char *saved_data = NULL;
-	int rc = 1;
-	char flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
+	env_t	env_new;
+	ssize_t	len;
+	char	*saved_data = NULL;
+	char	*res;
+	int	rc = 1;
+	char	flag = OBSOLETE_FLAG, new_flag = ACTIVE_FLAG;
 #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
-	ulong up_data = 0;
+	ulong	up_data = 0;
 #endif
 
-	debug ("Protect off %08lX ... %08lX\n",
+	debug("Protect off %08lX ... %08lX\n",
 		(ulong)flash_addr, end_addr);
 
-	if (flash_sect_protect (0, (ulong)flash_addr, end_addr)) {
-		goto Done;
+	if (flash_sect_protect(0, (ulong)flash_addr, end_addr)) {
+		goto done;
 	}
 
-	debug ("Protect off %08lX ... %08lX\n",
+	debug("Protect off %08lX ... %08lX\n",
 		(ulong)flash_addr_new, end_addr_new);
 
-	if (flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new)) {
-		goto Done;
+	if (flash_sect_protect(0, (ulong)flash_addr_new, end_addr_new)) {
+		goto done;
+	}
+
+	res = (char *)&env_new.data;
+	len = hexport('\0', &res, ENV_SIZE);
+	if (len < 0) {
+		error("Cannot export environment: errno = %d\n", errno);
+		goto done;
 	}
+	env_new.crc   = crc32(0, env_new.data, ENV_SIZE);
+	env_new.flags = new_flag;
 
 #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
 	up_data = (end_addr_new + 1 - ((long)flash_addr_new + CONFIG_ENV_SIZE));
-	debug ("Data to save 0x%x\n", up_data);
+	debug("Data to save 0x%lX\n", up_data);
 	if (up_data) {
 		if ((saved_data = malloc(up_data)) == NULL) {
 			printf("Unable to save the rest of sector (%ld)\n",
 				up_data);
-			goto Done;
+			goto done;
 		}
 		memcpy(saved_data,
 			(void *)((long)flash_addr_new + CONFIG_ENV_SIZE), up_data);
-		debug ("Data (start 0x%x, len 0x%x) saved at 0x%x\n",
-			   (long)flash_addr_new + CONFIG_ENV_SIZE,
-				up_data, saved_data);
+		debug("Data (start 0x%lX, len 0x%lX) saved at 0x%p\n",
+			(long)flash_addr_new + CONFIG_ENV_SIZE,
+			up_data, saved_data);
 	}
 #endif
-	puts ("Erasing Flash...");
-	debug (" %08lX ... %08lX ...",
+	puts("Erasing Flash...");
+	debug(" %08lX ... %08lX ...",
 		(ulong)flash_addr_new, end_addr_new);
 
-	if (flash_sect_erase ((ulong)flash_addr_new, end_addr_new)) {
-		goto Done;
+	if (flash_sect_erase((ulong)flash_addr_new, end_addr_new)) {
+		goto done;
 	}
 
-	puts ("Writing to Flash... ");
-	debug (" %08lX ... %08lX ...",
+	puts("Writing to Flash... ");
+	debug(" %08lX ... %08lX ...",
 		(ulong)&(flash_addr_new->data),
 		sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data));
-	if ((rc = flash_write((char *)env_ptr->data,
-			(ulong)&(flash_addr_new->data),
-			sizeof(env_ptr->data))) ||
-	    (rc = flash_write((char *)&(env_ptr->crc),
-			(ulong)&(flash_addr_new->crc),
-			sizeof(env_ptr->crc))) ||
+	if ((rc = flash_write((char *)&env_new,
+			(ulong)flash_addr_new,
+			sizeof(env_new))) ||
 	    (rc = flash_write(&flag,
 			(ulong)&(flash_addr->flags),
-			sizeof(flash_addr->flags))) ||
-	    (rc = flash_write(&new_flag,
-			(ulong)&(flash_addr_new->flags),
-			sizeof(flash_addr_new->flags))))
-	{
-		flash_perror (rc);
-		goto Done;
+			sizeof(flash_addr->flags))) ) {
+		flash_perror(rc);
+		goto done;
 	}
-	puts ("done\n");
 
 #if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
 	if (up_data) { /* restore the rest of sector */
-		debug ("Restoring the rest of data to 0x%x len 0x%x\n",
-			   (long)flash_addr_new + CONFIG_ENV_SIZE, up_data);
+		debug("Restoring the rest of data to 0x%lX len 0x%lX\n",
+			(long)flash_addr_new + CONFIG_ENV_SIZE, up_data);
 		if (flash_write(saved_data,
 				(long)flash_addr_new + CONFIG_ENV_SIZE,
 				up_data)) {
 			flash_perror(rc);
-			goto Done;
+			goto done;
 		}
 	}
 #endif
+	puts("done\n");
+
 	{
 		env_t * etmp = flash_addr;
 		ulong ltmp = end_addr;
@@ -220,13 +230,12 @@ int saveenv(void)
 	}
 
 	rc = 0;
-Done:
-
+done:
 	if (saved_data)
-		free (saved_data);
+		free(saved_data);
 	/* try to re-protect */
-	(void) flash_sect_protect (1, (ulong)flash_addr, end_addr);
-	(void) flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new);
+	(void) flash_sect_protect(1, (ulong)flash_addr, end_addr);
+	(void) flash_sect_protect(1, (ulong)flash_addr_new, end_addr_new);
 
 	return rc;
 }
@@ -244,83 +253,93 @@ int  env_init(void)
 
 	gd->env_addr  = (ulong)&default_environment[0];
 	gd->env_valid = 0;
-	return (0);
+	return 0;
 }
 
 #ifdef CMD_SAVEENV
 
 int saveenv(void)
 {
-	int	len, rc;
-	ulong	end_addr;
-	ulong	flash_sect_addr;
-#if defined(CONFIG_ENV_SECT_SIZE) && (CONFIG_ENV_SECT_SIZE >
 CONFIG_ENV_SIZE) -	ulong	flash_offset;
-	uchar	env_buffer[CONFIG_ENV_SECT_SIZE];
-#else
-	uchar *env_buffer = (uchar *)env_ptr;
-#endif	/* CONFIG_ENV_SECT_SIZE */
-	int rcode = 0;
-
-#if defined(CONFIG_ENV_SECT_SIZE) && (CONFIG_ENV_SECT_SIZE >

CONFIG_ENV_SIZE) -

common/env_flash.c +53 -33
-	flash_offset    = ((ulong)flash_addr) & (CONFIG_ENV_SECT_SIZE-1);
-	flash_sect_addr = ((ulong)flash_addr) & ~(CONFIG_ENV_SECT_SIZE-1);
-
-	debug ( "copy old content: "
-		"sect_addr: %08lX  env_addr: %08lX  offset: %08lX\n",
-		flash_sect_addr, (ulong)flash_addr, flash_offset);
-
-	/* copy old contents to temporary buffer */
-	memcpy (env_buffer, (void *)flash_sect_addr, CONFIG_ENV_SECT_SIZE);
-
-	/* copy current environment to temporary buffer */
-	memcpy ((uchar *)((unsigned long)env_buffer + flash_offset),
-		env_ptr,
-		CONFIG_ENV_SIZE);
+	env_t	env_new;
+	ssize_t	len;
+	int	rc = 1;
+	char	*res;
+	char	*saved_data = NULL;
+#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
+	ulong	up_data = 0;
 
-	len	 = CONFIG_ENV_SECT_SIZE;
-#else
-	flash_sect_addr = (ulong)flash_addr;
-	len	 = CONFIG_ENV_SIZE;
+	up_data = (end_addr + 1 - ((long)flash_addr + CONFIG_ENV_SIZE));
+	debug("Data to save 0x%lx\n", up_data);
+	if (up_data) {
+		if ((saved_data = malloc(up_data)) == NULL) {
+			printf("Unable to save the rest of sector (%ld)\n",
+				up_data);
+			goto done;
+		}
+		memcpy(saved_data,
+			(void *)((long)flash_addr + CONFIG_ENV_SIZE), up_data);
+		debug("Data (start 0x%lx, len 0x%lx) saved at 0x%lx\n",
+			(ulong)flash_addr + CONFIG_ENV_SIZE,
+			up_data,
+			(ulong)saved_data);
+	}
 #endif	/* CONFIG_ENV_SECT_SIZE */
 
-	end_addr = flash_sect_addr + len - 1;
+	debug("Protect off %08lX ... %08lX\n",
+		(ulong)flash_addr, end_addr);
 
-	debug ("Protect off %08lX ... %08lX\n",
-		(ulong)flash_sect_addr, end_addr);
+	if (flash_sect_protect(0, (long)flash_addr, end_addr))
+		goto done;
 
-	if (flash_sect_protect (0, flash_sect_addr, end_addr))
-		return 1;
+	res = (char *)&env_new.data;
+	len = hexport('\0', &res, ENV_SIZE);
+	if (len < 0) {
+		error("Cannot export environment: errno = %d\n", errno);
+		goto done;
+	}
+	env_new.crc = crc32(0, env_new.data, ENV_SIZE);
 
-	puts ("Erasing Flash...");
-	if (flash_sect_erase (flash_sect_addr, end_addr))
-		return 1;
+	puts("Erasing Flash...");
+	if (flash_sect_erase((long)flash_addr, end_addr))
+		goto done;
 
-	puts ("Writing to Flash... ");
-	rc = flash_write((char *)env_buffer, flash_sect_addr, len);
+	puts("Writing to Flash... ");
+	rc = flash_write((char *)&env_new, (long)flash_addr, CONFIG_ENV_SIZE);
 	if (rc != 0) {
-		flash_perror (rc);
-		rcode = 1;
-	} else {
-		puts ("done\n");
+		flash_perror(rc);
+		goto done;
 	}
-
+#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
+	if (up_data) {	/* restore the rest of sector */
+		debug("Restoring the rest of data to 0x%lx len 0x%lx\n",
+			(ulong)flash_addr + CONFIG_ENV_SIZE, up_data);
+		if (flash_write(saved_data,
+				(long)flash_addr + CONFIG_ENV_SIZE,
+				up_data)) {
+			flash_perror(rc);
+			goto done;
+		}
+	}
+#endif
+	puts("done\n");

common/env_flash.c int env_init(void) · line 332

Quoted 10 lines
common/env_flash.c +6 -2
+	rc = 0;
+done:
+	if (saved_data)
+		free(saved_data);
 	/* try to re-protect */
-	(void) flash_sect_protect (1, flash_sect_addr, end_addr);
-	return rcode;
+	(void) flash_sect_protect(1, (long)flash_addr, end_addr);
+	return rc;
 }

it would seem that somewhere nestled in this rewrite, support for embedded env was broken (CONFIG_ENV_SIZE < CONFIG_ENV_SECT_SIZE). on a bf548-ezkit for example, i see this behavior:

(v2010.09 / before this commit):
bfin> save
Saving Environment to Flash...
. done
Un-Protected 1 sectors
Erasing Flash...
. done
Erased 1 sectors
Writing to Flash... done
. done
Protected 1 sectors

(after this commit / v2010.12):
bfin> save
Saving Environment to Flash...
Error: start address not on sector boundary
Error: start address not on sector boundary

not sure if anyone has noticed/fixed this yet and would save me from the trouble of finding/fixing the problem ...
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101229/14330289/attachment.pgp

#38 lore raw

[U-Boot] env_flash.c:saveenv() broken when env is smaller than a sector

Quoted 79 lines · On Wednesday, December 29, 2010 20:53:17 Mike Frysinger wrote:
Quoted 51 lines · On Saturday, July 17, 2010 15:45:48 Wolfgang Denk wrote:
common/env_flash.c +0 -4
 int saveenv(void)
 {
 
-	int	len, rc;
-	ulong	end_addr;
-	ulong	flash_sect_addr;
-#if defined(CONFIG_ENV_SECT_SIZE) && (CONFIG_ENV_SECT_SIZE >

CONFIG_ENV_SIZE) - ulong flash_offset;

common/env_flash.c +0 -7
-	uchar	env_buffer[CONFIG_ENV_SECT_SIZE];
-#else
-	uchar *env_buffer = (uchar *)env_ptr;
-#endif	/* CONFIG_ENV_SECT_SIZE */
-	int rcode = 0;
-
-#if defined(CONFIG_ENV_SECT_SIZE) && (CONFIG_ENV_SECT_SIZE >

CONFIG_ENV_SIZE) -

common/env_flash.c +14 -18
-	flash_offset    = ((ulong)flash_addr) & (CONFIG_ENV_SECT_SIZE-1);
-	flash_sect_addr = ((ulong)flash_addr) & ~(CONFIG_ENV_SECT_SIZE-1);
-
-	debug ( "copy old content: "
-		"sect_addr: %08lX  env_addr: %08lX  offset: %08lX\n",
-		flash_sect_addr, (ulong)flash_addr, flash_offset);
-
-	/* copy old contents to temporary buffer */
-	memcpy (env_buffer, (void *)flash_sect_addr, CONFIG_ENV_SECT_SIZE);
-
-	/* copy current environment to temporary buffer */
-	memcpy ((uchar *)((unsigned long)env_buffer + flash_offset),
-		env_ptr,
-		CONFIG_ENV_SIZE);
+	env_t	env_new;
+	ssize_t	len;
+	int	rc = 1;
+	char	*res;
+	char	*saved_data = NULL;
+#if CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE
+	ulong	up_data = 0;
 
-	len	 = CONFIG_ENV_SECT_SIZE;
-#else
-	flash_sect_addr = (ulong)flash_addr;
-	len	 = CONFIG_ENV_SIZE;
+	up_data = (end_addr + 1 - ((long)flash_addr + CONFIG_ENV_SIZE));
+	debug("Data to save 0x%lx\n", up_data);
+	if (up_data) {
+		if ((saved_data = malloc(up_data)) == NULL) {
+			printf("Unable to save the rest of sector (%ld)\n",
+				up_data);
+			goto done;

common/env_flash.c int env_init(void)

Quoted 10 lines
common/env_flash.c +8 -0
+		}
+		memcpy(saved_data,
+			(void *)((long)flash_addr + CONFIG_ENV_SIZE), up_data);
+		debug("Data (start 0x%lx, len 0x%lx) saved at 0x%lx\n",
+			(ulong)flash_addr + CONFIG_ENV_SIZE,
+			up_data,
+			(ulong)saved_data);
+	}
 
 #endif	/* CONFIG_ENV_SECT_SIZE */

it would seem that somewhere nestled in this rewrite, support for embedded env was broken (CONFIG_ENV_SIZE < CONFIG_ENV_SECT_SIZE). on a bf548-ezkit for example, i see this behavior:

(v2010.09 / before this commit):
bfin> save
Saving Environment to Flash...
. done
Un-Protected 1 sectors
Erasing Flash...
. done
Erased 1 sectors
Writing to Flash... done
. done
Protected 1 sectors

Quoted 8 lines

(after this commit / v2010.12):
bfin> save
Saving Environment to Flash...
Error: start address not on sector boundary
Error: start address not on sector boundary

not sure if anyone has noticed/fixed this yet and would save me from the trouble of finding/fixing the problem ...

seems the new saveenv code in the non-redund case has been rewritten completely and doesn't support the same feature set as it used to.

old behavior:
- load up the entire sector
- overlay new env into sector
- round env start addr down to sector start
- round env end addr up to sector end
- protect/erase/save/protect whole sector

new behavior:
- load up the sector data after the env
- overlay new env into sector
- set env end addr to start of env plus one sector
- protect/erase/save/protect whole sector

so the difference is that the new code no longer supports envs which do not start on a sector boundary. it does this so that it doesn't memcpy() as much data out of the flash at the expense of doing more CPU bound math operations (mostly bit twiddling).

so the question is whether the old behavior should be restored. if it not, the documentation should be tweaked to note these requirements and some simple CPP checks added to environment.h so that this issue turns into a build failure. after all, it's easy to detect an env offset that isnt at the start of the sector:

	#if (CONFIG_ENV_OFFSET & (CONFIG_ENV_SECT_SIZE - 1))
	# error env offset not sector aligned
	#endif

-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101229/e28b1c0f/attachment.pgp

#39 lore raw

[U-Boot] env_flash.c:saveenv() broken when env is smaller than a sector

Dear Mike Frysinger,

Quoted 3 lines · In message <[email protected]> you wrote:

seems the new saveenv code in the non-redund case has been rewritten completely and doesn't support the same feature set as it used to.

...

Quoted 6 lines

so the difference is that the new code no longer supports envs which do not start on a sector boundary. it does this so that it doesn't memcpy() as much data out of the flash at the expense of doing more CPU bound math operations (mostly bit twiddling).

so the question is whether the old behavior should be restored. if it not,

The change was not intentional. Sorry.

I don't have a clear opinion if it's worth the effort to restore the old behavior - it seems it has never been used much (OK, you did).

Quoted 7 lines

the documentation should be tweaked to note these requirements and some simple CPP checks added to environment.h so that this issue turns into a build failure. after all, it's easy to detect an env offset that isnt at the start of the sector:

	#if (CONFIG_ENV_OFFSET & (CONFIG_ENV_SECT_SIZE - 1))
	# error env offset not sector aligned
	#endif

I agree that adding such a test would be a good thing - please submit a patch. Or one to restore the old behaviour, if you prefer.

Thanks.

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
e-credibility: the non-guaranteeable likelihood that  the  electronic
data you're seeing is genuine rather than somebody's made-up crap.
- Karl Lehenbauer
#40 lore raw

cover New environment code

In reply to Wolfgang Denk
Quoted 3 lines · In message <[email protected]> you wrote:

The following patch series adds some utilities (qsort and hash table based database functions) and uses these to reimplement the code used for the internal handling of environment variables.

Note: the patches are also available for easier testing as branch "hashtable" in the u-boot-testing repository, see
git://git.denx.de/u-boot-testing.git

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"It is easier to port a shell than a shell script."      - Larry Wall
#41 lore raw

cover New environment code

In reply to Wolfgang Denk
Quoted 5 lines · Wolfgang Denk

The following patch series adds some utilities (qsort and hash table based database functions) and uses these to reimplement the code used for the internal handling of environment variables.

Quoted 9 lines

Motivation:

* Old environment code used a pessimizing implementation:
- variable lookup used linear search => slow
- changed/added variables were added at the end, i. e. most frequently used variables had the slowest access times => slow
- each setenv() would calculate the CRC32 checksum over the whole environment block => slow

Hello Wolfgang,

how many users are out there that have such huge environments that speed is of any concern?
The "grepenv" idea however seems to indicate some might have huge environments...

I see the advantages offered, but

Quoted 5 lines

Disadvantages:

- Image size grows by typically 5...7 KiB (might shrink a bit again on systems with redundant environment with a following patch series)

Looking at the patches I can't really see where that large increase in image size comes from;
but if its really true, it seems to be a very high price to pay for those who get along with the
environment as it is.
I would at least recommend that all new UI commands are optional; as basics "setenv", "printenv", "saveenv" should do as until now. "export" and "import" must be adding
a lot to the code.

Best Regards,
Reinhard

#42 lore raw

cover New environment code

Quoted 11 lines · On Saturday, July 17, 2010 16:56:43 Reinhard Meyer wrote:
Quoted 5 lines · Wolfgang Denk

Disadvantages:

- Image size grows by typically 5...7 KiB (might shrink a bit again on

systems with redundant environment with a following patch series)

Looking at the patches I can't really see where that large increase in image size comes from;
but if its really true, it seems to be a very high price to pay for those who get along with the environment as it is.

i wonder if we could #ifdef the sorting/hashing. i tend to agree with Reinhard that it is very common for boards to be deployed with a small env, so i wonder if the normal runtime experience is actually faster, or if the difference is about the same as system noise: boot u-boot, load env with ~20 entries, read a few env vars, boot OS.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100717/f2dfacfc/attachment.pgp

#43 lore raw

cover New environment code

Dear Mike Frysinger,

Quoted 2 lines · In message <[email protected]> you wrote:

i wonder if we could #ifdef the sorting/hashing. i tend to agree with

The sorting does not take much:

	-> size lib/qsort.o  
	   text    data     bss     dec     hex filename
	    264       0       0     264     108 lib/qsort.o

The hashing on the other hand might be replacable.

Quoted 4 lines

Reinhard that it is very common for boards to be deployed with a small env, so i wonder if the normal runtime experience is actually faster, or if the difference is about the same as system noise: boot u-boot, load env with ~20 entries, read a few env vars, boot OS.

Yes, this is one common use case.

But then, I see also systems that are running pretty complex shell scripts to implement features like reliable software updates etc., and there we see an improvment.

Also, speed is just one aspect - for me the capability of having several "profiles" is much, much more important.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
It is more rational to sacrifice one life than six.
	-- Spock, "The Galileo Seven", stardate 2822.3
#44 lore raw

cover New environment code

Quoted 8 lines · On Saturday, July 17, 2010 17:41:57 Wolfgang Denk wrote:
Quoted 4 lines · Mike Frysinger

Reinhard that it is very common for boards to be deployed with a small env, so i wonder if the normal runtime experience is actually faster, or if the difference is about the same as system noise: boot u-boot, load env with ~20 entries, read a few env vars, boot OS.

Yes, this is one common use case.

Quoted 7 lines

But then, I see also systems that are running pretty complex shell scripts to implement features like reliable software updates etc., and there we see an improvment.

Also, speed is just one aspect - for me the capability of having several "profiles" is much, much more important.

which is why i suggested an ifdef. i didnt say the features you're introducing arent useful to many people, just that they are not necessary to many others.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20100717/39a90e9f/attachment.pgp

#45 lore raw

cover New environment code

In reply to Reinhard Meyer

Dear Reinhard Meyer,

Quoted 3 lines · In message <[email protected]> you wrote:

how many users are out there that have such huge environments that speed is of any concern?

This is not so much a question of huge environments. Even with small environments (say, 2 kb) speed may quickly become an issue - see for example here:
http://www.denx.de/wiki/DULG/AN2004_11_BootTimeOptimization (Step 2)

Even worse is the fact that the old code recomputes the CRC over the whole environment for each and every "setenv" - and for example a network download will run 4 (or more) "setenv" commands internally...

Or remember the tricks that were necessary to get netconsole and serial console work in parallel...

And so on... the deeper you look, the more issues you will find with the old code. It has been designed to be simple to implement, but we added a lot of usage modes since, and while I still think it's a pretty efficient format for external storage, we need more efficient ways when internally accessing the environment files.

Quoted 9 lines

The "grepenv" idea however seems to indicate some might have huge environments...

I see the advantages offered, but

Quoted 4 lines

Disadvantages:

- Image size grows by typically 5...7 KiB (might shrink a bit again on systems with redundant environment with a following patch series)

Yes, it's some 2...3% on many systems...

Quoted 2 lines

Looking at the patches I can't really see where that large increase in image size comes from;

Well, the hashtable code itself adds some 3 kB, a few hundret bytes are needed for qsort, etc.

Quoted 3 lines

but if its really true, it seems to be a very high price to pay for those who get along with the
environment as it is.

I hear you.

Quoted 4 lines

I would at least recommend that all new UI commands are optional; as basics "setenv", "printenv", "saveenv" should do as until now. "export" and "import" must be adding
a lot to the code.

Actually it's not that much, and the code is needed anyway as it is used to read (import) the environment as stored in flash / nand / whatever into the hash table when booting, and to export it again when running "saveenv". The remaining UI commands are tiny; they don't consume any significant space.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A Freudian slip is when you say one thing but mean your mother.
#46 lore raw

cover New environment code

In reply to Wolfgang Denk
Quoted 6 lines · In message <[email protected]> I wrote:

The following patch series adds some utilities (qsort and hash table based database functions) and uses these to reimplement the code used for the internal handling of environment variables.

Quoted 8 lines

Motivation:

* Old environment code used a pessimizing implementation:
- variable lookup used linear search => slow
- changed/added variables were added at the end, i. e. most frequently used variables had the slowest access times => slow
- each setenv() would calculate the CRC32 checksum over the whole environment block => slow

Just to give a datapoint for speed:

measured on TQM5200 (MPC5200 at 400 MHz, environment size 16 kB):

OLD implementation:

	=> sete ttt 'date;for i in 0 1 2 3 4 5 6 7 8 9 ; do for j in 0 1 2 3 4 5 6 7 8 9 ; do for k in 0 1 2 3 4 5 6 7 8 9 ; do run tt ; done ; done ; done;date'
	=> sete tt 'sete var1 xxx;sete var2 ${var1};sete var1 ${var2};sete var1;sete var2'
	=> run tt
	=> run ttt
	Date: 1910-07-17 (unknown day)    Time: 22:02:31
	Date: 1910-07-17 (unknown day)    Time: 22:03:27

New implementation:

	=> run ttt
	Date: 1910-07-17 (unknown day)    Time: 20:45:51
	Date: 1910-07-17 (unknown day)    Time: 20:45:53

I. e. we have 56 versus 2 seconds.

I haven't run intensive tests, but in general I think we can see that scripts referncing environment variables will typically run faster by a factor of 10, or more.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Time is an illusion perpetrated by the manufacturers of space.
#47 lore raw

cover New environment code

Quoted 13 lines · Wolfgang Denk

Just to give a datapoint for speed:

measured on TQM5200 (MPC5200 at 400 MHz, environment size 16 kB):

OLD implementation:

	=> sete ttt 'date;for i in 0 1 2 3 4 5 6 7 8 9 ; do for j in 0 1 2 3 4 5 6 7 8 9 ; do for k in 0 1 2 3 4 5 6 7 8 9 ; do run tt ; done ; done ; done;date'
	=> sete tt 'sete var1 xxx;sete var2 ${var1};sete var1 ${var2};sete var1;sete var2'
	=> run tt
	=> run ttt
	Date: 1910-07-17 (unknown day)    Time: 22:02:31
	Date: 1910-07-17 (unknown day)    Time: 22:03:27
Quoted 7 lines

New implementation:

	=> run ttt
	Date: 1910-07-17 (unknown day)    Time: 20:45:51
	Date: 1910-07-17 (unknown day)    Time: 20:45:53

<joke>I'd propose a contest for the most hilarious use of a BOOTLOADER.....</joke>

But, how does the timing look in the current implementation when the CRC calculation
is done only in the saveenv command?

Best Regards,
Reinhard

#48 lore raw

cover New environment code

Dear Reinhard Meyer,

Quoted 4 lines · In message <[email protected]> you wrote:

But, how does the timing look in the current implementation when the CRC calculation
is done only in the saveenv command?

I don't know. Much better for the old code, obviously. But you still have the efforts for the linear search, usually way to the end of the environment.

Best regards,

Wolfgang Denk

Signature · 4 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Save yourself!  Reboot in 5 seconds!
#49 lore raw

cover New environment code

In reply to Wolfgang Denk
Quoted 3 lines · On Saturday, July 17, 2010 15:45:43 Wolfgang Denk wrote:

The following patch series adds some utilities (qsort and hash table based database functions) and uses these to reimplement the code used for the internal handling of environment variables.

seems to break autocompletion CONFIG_AUTO_COMPLETE :(

if i checkout the previous commit (0fe247b973d9b8f7e2c04cc159fcdd2e64591e55), things work fine. but checking out the env change and it no longer works. -mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101020/efa120a3/attachment.pgp

#50 lore raw

cover New environment code

Dear Mike Frysinger,

Quoted 6 lines · In message <[email protected]> you wrote:
Quoted 4 lines

The following patch series adds some utilities (qsort and hash table based database functions) and uses these to reimplement the code used for the internal handling of environment variables.

seems to break autocompletion CONFIG_AUTO_COMPLETE :(

Yes, this was already noted and discussed before.

I'm still not sure how to (re-) add this optimally.

Best regards,

Wolfgang Denk

Signature · 6 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
It became apparent that one reason why the Ice Giants were  known  as
the  Ice  Giants  was  because they were, well, giants. The other was
that they were made of ice.              -Terry Pratchett, _Sourcery_
#51 lore raw

cover New environment code

In reply to Wolfgang Denk
Quoted 19 lines · On Saturday, July 17, 2010 15:45:43 Wolfgang Denk wrote:

TODO:

- drop default env as implemented now; provide a text file based initialization instead (eventually using several text files to incrementally build it from common blocks) and a tool to convert it into a binary blob / object file.

- It would be nice if we could add wildcard support for environment variables; this is needed for variable name auto-completion, but it would also be nice to be able to say "printenv ip*" or "printenv *addr*"

- Some boards don't link any more due to the grown code size:
AR405, CANBT, DU405, PMC440, canyonlands, sc3, sequoia, socrates.

=> cc: Matthias Fuchs <[email protected]>,
Stefan Roese <[email protected]>,
Heiko Schocher <[email protected]>

Quoted 6 lines

- Dropping forceenv() causes build problems on schmoogie

=> cc: Sergey Kubushyn <[email protected]>

- Build tested on PPC and ARM only; runtime tested with NOR and NAND flash only => needs testing!!

seems that some todo items are missing, or not well implied. for example, it seems that gd->env_addr needs to be punted, and these functions get a "_f" appended to their name since they only work on default_environment[] now:

	env_get_addr()
	env_get_char()
	env_get_char_memory()
	envmatch()

-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101208/1eb3dd09/attachment.pgp

#52 lore raw

cover New environment code

Dear Mike Frysinger,

Quoted 8 lines · In message <[email protected]> you wrote:

seems that some todo items are missing, or not well implied. for example, it seems that gd->env_addr needs to be punted, and these functions get a "_f" appended to their name since they only work on default_environment[] now:

	env_get_addr()
	env_get_char()
	env_get_char_memory()
	envmatch()

I'm not sure I understand what you mean.

These functions not NOT only operate on the default_environment[]; they are also used to access the normal environment before relocation.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
"If that makes any sense to you, you have a big problem."
                                  -- C. Durance, Computer Science 234
#53 lore raw

cover New environment code

Quoted 10 lines · On Wednesday, December 08, 2010 05:04:42 Wolfgang Denk wrote:
Quoted 8 lines · Mike Frysinger

seems that some todo items are missing, or not well implied. for example, it seems that gd->env_addr needs to be punted, and these functions get a "_f" appended to their name since they only work on default_environment[] now:

	env_get_addr()
	env_get_char()
	env_get_char_memory()
	envmatch()
Quoted 5 lines

I'm not sure I understand what you mean.

These functions not NOT only operate on the default_environment[]; they are also used to access the normal environment before relocation.

my point is that they cannot be used after relocation and once the env is moved into the hash table. currently, they dont return any errors if someone attempts to do so and while it might seem like the funcs are working, they only parse the default env.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20101208/71915c79/attachment.pgp