diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile | 1 | ||||
| -rw-r--r-- | lib/fdtdec.c | 2 | ||||
| -rw-r--r-- | lib/hashtable.c | 244 | ||||
| -rw-r--r-- | lib/linux_string.c | 51 | ||||
| -rw-r--r-- | lib/sha1.c | 19 | ||||
| -rw-r--r-- | lib/sha256.c | 37 | ||||
| -rw-r--r-- | lib/string.c | 55 | ||||
| -rw-r--r-- | lib/vsprintf.c | 2 | 
8 files changed, 279 insertions, 132 deletions
| diff --git a/lib/Makefile b/lib/Makefile index f83f6e8d8..86ca1a6ec 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -69,6 +69,7 @@ endif  COBJS-y += crc32.o  COBJS-y += ctype.o  COBJS-y += div64.o +COBJS-y += linux_string.o  COBJS-y += string.o  COBJS-y += time.o  COBJS-$(CONFIG_BOOTP_PXE) += uuid.o diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 348144aa7..6dba4389f 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -43,6 +43,8 @@ static const char * const compat_names[COMPAT_COUNT] = {  	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),  	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"),  	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), +	COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"), +	COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),  };  const char *fdtdec_get_compatible(enum fdt_compat_id id) diff --git a/lib/hashtable.c b/lib/hashtable.c index 94a7b6171..07ebfb218 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -54,7 +54,9 @@  #define	CONFIG_ENV_MAX_ENTRIES 512  #endif -#include "search.h" +#include <env_callback.h> +#include <env_flags.h> +#include <search.h>  /*   * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 @@ -66,12 +68,16 @@   * Instead the interface of all functions is extended to take an argument   * which describes the current status.   */ +  typedef struct _ENTRY {  	int used;  	ENTRY entry;  } _ENTRY; +static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep, +	int idx); +  /*   * hcreate()   */ @@ -142,7 +148,7 @@ int hcreate_r(size_t nel, struct hsearch_data *htab)   * be freed and the local static variable can be marked as not used.   */ -void hdestroy_r(struct hsearch_data *htab, int do_apply) +void hdestroy_r(struct hsearch_data *htab)  {  	int i; @@ -156,10 +162,7 @@ void hdestroy_r(struct hsearch_data *htab, int do_apply)  	for (i = 1; i <= htab->size; ++i) {  		if (htab->table[i].used > 0) {  			ENTRY *ep = &htab->table[i].entry; -			if (do_apply && htab->apply != NULL) { -				/* deletion is always forced */ -				htab->apply(ep->key, ep->data, NULL, H_FORCE); -			} +  			free((void *)ep->key);  			free(ep->data);  		} @@ -250,14 +253,65 @@ int hmatch_r(const char *match, int last_idx, ENTRY ** retval,  	return 0;  } +/* + * Compare an existing entry with the desired key, and overwrite if the action + * is ENTER.  This is simply a helper function for hsearch_r(). + */ +static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action, +	ENTRY **retval, struct hsearch_data *htab, int flag, +	unsigned int hval, unsigned int idx) +{ +	if (htab->table[idx].used == hval +	    && strcmp(item.key, htab->table[idx].entry.key) == 0) { +		/* Overwrite existing value? */ +		if ((action == ENTER) && (item.data != NULL)) { +			/* check for permission */ +			if (htab->change_ok != NULL && htab->change_ok( +			    &htab->table[idx].entry, item.data, +			    env_op_overwrite, flag)) { +				debug("change_ok() rejected setting variable " +					"%s, skipping it!\n", item.key); +				__set_errno(EPERM); +				*retval = NULL; +				return 0; +			} + +			/* If there is a callback, call it */ +			if (htab->table[idx].entry.callback && +			    htab->table[idx].entry.callback(item.key, +			    item.data, env_op_overwrite, flag)) { +				debug("callback() rejected setting variable " +					"%s, skipping it!\n", item.key); +				__set_errno(EINVAL); +				*retval = NULL; +				return 0; +			} + +			free(htab->table[idx].entry.data); +			htab->table[idx].entry.data = strdup(item.data); +			if (!htab->table[idx].entry.data) { +				__set_errno(ENOMEM); +				*retval = NULL; +				return 0; +			} +		} +		/* return found entry */ +		*retval = &htab->table[idx].entry; +		return idx; +	} +	/* keep searching */ +	return -1; +} +  int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval, -	      struct hsearch_data *htab) +	      struct hsearch_data *htab, int flag)  {  	unsigned int hval;  	unsigned int count;  	unsigned int len = strlen(item.key);  	unsigned int idx;  	unsigned int first_deleted = 0; +	int ret;  	/* Compute an value for the given string. Perhaps use a better method. */  	hval = len; @@ -289,23 +343,10 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,  		    && !first_deleted)  			first_deleted = idx; -		if (htab->table[idx].used == hval -		    && strcmp(item.key, htab->table[idx].entry.key) == 0) { -			/* Overwrite existing value? */ -			if ((action == ENTER) && (item.data != NULL)) { -				free(htab->table[idx].entry.data); -				htab->table[idx].entry.data = -					strdup(item.data); -				if (!htab->table[idx].entry.data) { -					__set_errno(ENOMEM); -					*retval = NULL; -					return 0; -				} -			} -			/* return found entry */ -			*retval = &htab->table[idx].entry; -			return idx; -		} +		ret = _compare_and_overwrite_entry(item, action, retval, htab, +			flag, hval, idx); +		if (ret != -1) +			return ret;  		/*  		 * Second hash function: @@ -331,23 +372,10 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,  				break;  			/* If entry is found use it. */ -			if ((htab->table[idx].used == hval) -			    && strcmp(item.key, htab->table[idx].entry.key) == 0) { -				/* Overwrite existing value? */ -				if ((action == ENTER) && (item.data != NULL)) { -					free(htab->table[idx].entry.data); -					htab->table[idx].entry.data = -						strdup(item.data); -					if (!htab->table[idx].entry.data) { -						__set_errno(ENOMEM); -						*retval = NULL; -						return 0; -					} -				} -				/* return found entry */ -				*retval = &htab->table[idx].entry; -				return idx; -			} +			ret = _compare_and_overwrite_entry(item, action, retval, +				htab, flag, hval, idx); +			if (ret != -1) +				return ret;  		}  		while (htab->table[idx].used);  	} @@ -383,6 +411,34 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,  		++htab->filled; +		/* This is a new entry, so look up a possible callback */ +		env_callback_init(&htab->table[idx].entry); +		/* Also look for flags */ +		env_flags_init(&htab->table[idx].entry); + +		/* check for permission */ +		if (htab->change_ok != NULL && htab->change_ok( +		    &htab->table[idx].entry, item.data, env_op_create, flag)) { +			debug("change_ok() rejected setting variable " +				"%s, skipping it!\n", item.key); +			_hdelete(item.key, htab, &htab->table[idx].entry, idx); +			__set_errno(EPERM); +			*retval = NULL; +			return 0; +		} + +		/* If there is a callback, call it */ +		if (htab->table[idx].entry.callback && +		    htab->table[idx].entry.callback(item.key, item.data, +		    env_op_create, flag)) { +			debug("callback() rejected setting variable " +				"%s, skipping it!\n", item.key); +			_hdelete(item.key, htab, &htab->table[idx].entry, idx); +			__set_errno(EINVAL); +			*retval = NULL; +			return 0; +		} +  		/* return new entry */  		*retval = &htab->table[idx].entry;  		return 1; @@ -404,7 +460,21 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,   * do that.   */ -int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply) +static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep, +	int idx) +{ +	/* free used ENTRY */ +	debug("hdelete: DELETING key \"%s\"\n", key); +	free((void *)ep->key); +	free(ep->data); +	ep->callback = NULL; +	ep->flags = 0; +	htab->table[idx].used = -1; + +	--htab->filled; +} + +int hdelete_r(const char *key, struct hsearch_data *htab, int flag)  {  	ENTRY e, *ep;  	int idx; @@ -413,20 +483,31 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)  	e.key = (char *)key; -	if ((idx = hsearch_r(e, FIND, &ep, htab)) == 0) { +	idx = hsearch_r(e, FIND, &ep, htab, 0); +	if (idx == 0) {  		__set_errno(ESRCH);  		return 0;	/* not found */  	} -	/* free used ENTRY */ -	debug("hdelete: DELETING key \"%s\"\n", key); -	if (do_apply && htab->apply != NULL) -		htab->apply(ep->key, ep->data, NULL, H_FORCE); -	free((void *)ep->key); -	free(ep->data); -	htab->table[idx].used = -1; +	/* Check for permission */ +	if (htab->change_ok != NULL && +	    htab->change_ok(ep, NULL, env_op_delete, flag)) { +		debug("change_ok() rejected deleting variable " +			"%s, skipping it!\n", key); +		__set_errno(EPERM); +		return 0; +	} -	--htab->filled; +	/* If there is a callback, call it */ +	if (htab->table[idx].entry.callback && +	    htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) { +		debug("callback() rejected deleting variable " +			"%s, skipping it!\n", key); +		__set_errno(EINVAL); +		return 0; +	} + +	_hdelete(key, htab, ep, idx);  	return 1;  } @@ -482,7 +563,7 @@ static int cmpkey(const void *p1, const void *p2)  	return (strcmp(e1->key, e2->key));  } -ssize_t hexport_r(struct hsearch_data *htab, const char sep, +ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,  		 char **resp, size_t size,  		 int argc, char * const argv[])  { @@ -519,6 +600,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,  			if ((argc > 0) && (found == 0))  				continue; +			if ((flag & H_HIDE_DOT) && ep->key[0] == '.') +				continue; +  			list[n++] = ep;  			totlen += strlen(ep->key) + 2; @@ -674,7 +758,7 @@ static int drop_var_from_set(const char *name, int nvars, char * vars[])  int himport_r(struct hsearch_data *htab,  		const char *env, size_t size, const char sep, int flag, -		int nvars, char * const vars[], int do_apply) +		int nvars, char * const vars[])  {  	char *data, *sp, *dp, *name, *value;  	char *localvars[nvars]; @@ -704,7 +788,7 @@ int himport_r(struct hsearch_data *htab,  		debug("Destroy Hash Table: %p table = %p\n", htab,  		       htab->table);  		if (htab->table) -			hdestroy_r(htab, do_apply); +			hdestroy_r(htab);  	}  	/* @@ -770,7 +854,7 @@ int himport_r(struct hsearch_data *htab,  			if (!drop_var_from_set(name, nvars, localvars))  				continue; -			if (hdelete_r(name, htab, do_apply) == 0) +			if (hdelete_r(name, htab, flag) == 0)  				debug("DELETE ERROR ##############################\n");  			continue; @@ -794,30 +878,10 @@ int himport_r(struct hsearch_data *htab,  		e.key = name;  		e.data = value; -		/* if there is an apply function, check what it has to say */ -		if (do_apply && htab->apply != NULL) { -			debug("searching before calling cb function" -				" for  %s\n", name); -			/* -			 * Search for variable in existing env, so to pass -			 * its previous value to the apply callback -			 */ -			hsearch_r(e, FIND, &rv, htab); -			debug("previous value was %s\n", rv ? rv->data : ""); -			if (htab->apply(name, rv ? rv->data : NULL, -				value, flag)) { -				debug("callback function refused to set" -					" variable %s, skipping it!\n", name); -				continue; -			} -		} - -		hsearch_r(e, ENTER, &rv, htab); -		if (rv == NULL) { +		hsearch_r(e, ENTER, &rv, htab, flag); +		if (rv == NULL)  			printf("himport_r: can't insert \"%s=%s\" into hash table\n",  				name, value); -			return 0; -		}  		debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",  			htab, htab->filled, htab->size, @@ -839,7 +903,7 @@ int himport_r(struct hsearch_data *htab,  		 * b) if the variable was not present in current env, we notify  		 *    it might be a typo  		 */ -		if (hdelete_r(localvars[i], htab, do_apply) == 0) +		if (hdelete_r(localvars[i], htab, flag) == 0)  			printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);  		else  			printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]); @@ -848,3 +912,27 @@ int himport_r(struct hsearch_data *htab,  	debug("INSERT: done\n");  	return 1;		/* everything OK */  } + +/* + * hwalk_r() + */ + +/* + * Walk all of the entries in the hash, calling the callback for each one. + * this allows some generic operation to be performed on each element. + */ +int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *)) +{ +	int i; +	int retval; + +	for (i = 1; i <= htab->size; ++i) { +		if (htab->table[i].used > 0) { +			retval = callback(&htab->table[i].entry); +			if (retval) +				return retval; +		} +	} + +	return 0; +} diff --git a/lib/linux_string.c b/lib/linux_string.c new file mode 100644 index 000000000..d5a5e08d9 --- /dev/null +++ b/lib/linux_string.c @@ -0,0 +1,51 @@ +/* + *  linux/lib/string.c + * + *  Copyright (C) 1991, 1992  Linus Torvalds + */ + +#ifdef USE_HOSTCC +#include <stdio.h> +#endif + +#include <linux/ctype.h> +#include <linux/string.h> + +/** + * skip_spaces - Removes leading whitespace from @str. + * @str: The string to be stripped. + * + * Returns a pointer to the first non-whitespace character in @str. + */ +char *skip_spaces(const char *str) +{ +	while (isspace(*str)) +		++str; +	return (char *)str; +} + +/** + * strim - Removes leading and trailing whitespace from @s. + * @s: The string to be stripped. + * + * Note that the first trailing whitespace is replaced with a %NUL-terminator + * in the given string @s. Returns a pointer to the first non-whitespace + * character in @s. + */ +char *strim(char *s) +{ +	size_t size; +	char *end; + +	s = skip_spaces(s); +	size = strlen(s); +	if (!size) +		return s; + +	end = s + size - 1; +	while (end >= s && isspace(*end)) +		end--; +	*(end + 1) = '\0'; + +	return s; +} diff --git a/lib/sha1.c b/lib/sha1.c index da5bc16f3..a12122485 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -73,7 +73,7 @@ void sha1_starts (sha1_context * ctx)  	ctx->state[4] = 0xC3D2E1F0;  } -static void sha1_process (sha1_context * ctx, unsigned char data[64]) +static void sha1_process(sha1_context *ctx, const unsigned char data[64])  {  	unsigned long temp, W[16], A, B, C, D, E; @@ -230,7 +230,8 @@ static void sha1_process (sha1_context * ctx, unsigned char data[64])  /*   * SHA-1 process buffer   */ -void sha1_update (sha1_context * ctx, unsigned char *input, int ilen) +void sha1_update(sha1_context *ctx, const unsigned char *input, +		 unsigned int ilen)  {  	int fill;  	unsigned long left; @@ -305,7 +306,8 @@ void sha1_finish (sha1_context * ctx, unsigned char output[20])  /*   * Output = SHA-1( input buffer )   */ -void sha1_csum (unsigned char *input, int ilen, unsigned char output[20]) +void sha1_csum(const unsigned char *input, unsigned int ilen, +	       unsigned char *output)  {  	sha1_context ctx; @@ -318,12 +320,12 @@ void sha1_csum (unsigned char *input, int ilen, unsigned char output[20])   * Output = SHA-1( input buffer ). Trigger the watchdog every 'chunk_sz'   * bytes of input processed.   */ -void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20], -			unsigned int chunk_sz) +void sha1_csum_wd(const unsigned char *input, unsigned int ilen, +		  unsigned char *output, unsigned int chunk_sz)  {  	sha1_context ctx;  #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) -	unsigned char *end, *curr; +	const unsigned char *end, *curr;  	int chunk;  #endif @@ -350,8 +352,9 @@ void sha1_csum_wd (unsigned char *input, int ilen, unsigned char output[20],  /*   * Output = HMAC-SHA-1( input buffer, hmac key )   */ -void sha1_hmac (unsigned char *key, int keylen, -		unsigned char *input, int ilen, unsigned char output[20]) +void sha1_hmac(const unsigned char *key, int keylen, +	       const unsigned char *input, unsigned int ilen, +	       unsigned char *output)  {  	int i;  	sha1_context ctx; diff --git a/lib/sha256.c b/lib/sha256.c index deb63a40b..ab2db4890 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -60,7 +60,7 @@ void sha256_starts(sha256_context * ctx)  	ctx->state[7] = 0x5BE0CD19;  } -void sha256_process(sha256_context * ctx, uint8_t data[64]) +static void sha256_process(sha256_context *ctx, const uint8_t data[64])  {  	uint32_t temp1, temp2;  	uint32_t W[64]; @@ -191,7 +191,7 @@ void sha256_process(sha256_context * ctx, uint8_t data[64])  	ctx->state[7] += H;  } -void sha256_update(sha256_context * ctx, uint8_t * input, uint32_t length) +void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)  {  	uint32_t left, fill; @@ -260,3 +260,36 @@ void sha256_finish(sha256_context * ctx, uint8_t digest[32])  	PUT_UINT32_BE(ctx->state[6], digest, 24);  	PUT_UINT32_BE(ctx->state[7], digest, 28);  } + +/* + * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha256_csum_wd(const unsigned char *input, unsigned int ilen, +		unsigned char *output, unsigned int chunk_sz) +{ +	sha256_context ctx; +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) +	unsigned char *end, *curr; +	int chunk; +#endif + +	sha256_starts(&ctx); + +#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) +	curr = input; +	end = input + ilen; +	while (curr < end) { +		chunk = end - curr; +		if (chunk > chunk_sz) +			chunk = chunk_sz; +		sha256_update(&ctx, curr, chunk); +		curr += chunk; +		WATCHDOG_RESET(); +	} +#else +	sha256_update(&ctx, input, ilen); +#endif + +	sha256_finish(&ctx, output); +} diff --git a/lib/string.c b/lib/string.c index c3ad055e2..09dfae03c 100644 --- a/lib/string.c +++ b/lib/string.c @@ -21,14 +21,13 @@  #include <malloc.h> -#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */  /** - * strnicmp - Case insensitive, length-limited string comparison + * strncasecmp - Case insensitive, length-limited string comparison   * @s1: One string   * @s2: The other string   * @len: the maximum number of characters to compare   */ -int strnicmp(const char *s1, const char *s2, size_t len) +int strncasecmp(const char *s1, const char *s2, size_t len)  {  	/* Yes, Virginia, it had better be unsigned */  	unsigned char c1, c2; @@ -52,7 +51,16 @@ int strnicmp(const char *s1, const char *s2, size_t len)  	}  	return (int)c1 - (int)c2;  } -#endif + +/** + * strcasecmp - Case insensitive string comparison + * @s1: One string + * @s2: The other string + */ +int strcasecmp(const char *s1, const char *s2) +{ +	return strncasecmp(s1, s2, -1U); +}  char * ___strtok; @@ -214,45 +222,6 @@ char * strrchr(const char * s, int c)  }  #endif - -/** - * skip_spaces - Removes leading whitespace from @str. - * @str: The string to be stripped. - * - * Returns a pointer to the first non-whitespace character in @str. - */ -char *skip_spaces(const char *str) -{ -	while (isspace(*str)) -		++str; -	return (char *)str; -} - -/** - * strim - Removes leading and trailing whitespace from @s. - * @s: The string to be stripped. - * - * Note that the first trailing whitespace is replaced with a %NUL-terminator - * in the given string @s. Returns a pointer to the first non-whitespace - * character in @s. - */ -char *strim(char *s) -{ -	size_t size; -	char *end; - -	s = skip_spaces(s); -	size = strlen(s); -	if (!size) -		return s; - -	end = s + size - 1; -	while (end >= s && isspace(*end)) -		end--; -	*(end + 1) = '\0'; - -	return s; -}  #ifndef __HAVE_ARCH_STRLEN  /**   * strlen - Find the length of a string diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b7a79c0e0..3c432f876 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -103,7 +103,7 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)  	return simple_strtoul(cp, endp, base);  } -int ustrtoul(const char *cp, char **endp, unsigned int base) +unsigned long ustrtoul(const char *cp, char **endp, unsigned int base)  {  	unsigned long result = simple_strtoul(cp, endp, base);  	switch (**endp) { |