diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/fdtdec.c | 31 | ||||
| -rw-r--r-- | lib/hashtable.c | 95 | 
2 files changed, 109 insertions, 17 deletions
| diff --git a/lib/fdtdec.c b/lib/fdtdec.c index cc09e06c7..4c23f458f 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -24,8 +24,7 @@  #include <libfdt.h>  #include <fdtdec.h> -/* we need the generic GPIO interface here */ -#include <asm-generic/gpio.h> +#include <asm/gpio.h>  DECLARE_GLOBAL_DATA_PTR; @@ -43,6 +42,7 @@ static const char * const compat_names[COMPAT_COUNT] = {  	COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),  	COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),  	COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"), +	COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),  };  const char *fdtdec_get_compatible(enum fdt_compat_id id) @@ -80,11 +80,16 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node,  	const fdt_addr_t *cell;  	int len; -	debug("get_addr: %s\n", prop_name); +	debug("%s: %s: ", __func__, prop_name);  	cell = fdt_getprop(blob, node, prop_name, &len);  	if (cell && (len == sizeof(fdt_addr_t) || -			len == sizeof(fdt_addr_t) * 2)) -		return fdt_addr_to_cpu(*cell); +			len == sizeof(fdt_addr_t) * 2)) { +		fdt_addr_t addr = fdt_addr_to_cpu(*cell); + +		debug("%p\n", (void *)addr); +		return addr; +	} +	debug("(not found)\n");  	return FDT_ADDR_T_NONE;  } @@ -94,10 +99,15 @@ s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,  	const s32 *cell;  	int len; -	debug("get_size: %s\n", prop_name); +	debug("%s: %s: ", __func__, prop_name);  	cell = fdt_getprop(blob, node, prop_name, &len); -	if (cell && len >= sizeof(s32)) -		return fdt32_to_cpu(cell[0]); +	if (cell && len >= sizeof(s32)) { +		s32 val = fdt32_to_cpu(cell[0]); + +		debug("%#x (%d)\n", val, val); +		return val; +	} +	debug("(not found)\n");  	return default_val;  } @@ -329,6 +339,7 @@ int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name)  	const u32 *phandle;  	int lookup; +	debug("%s: %s\n", __func__, prop_name);  	phandle = fdt_getprop(blob, node, prop_name, NULL);  	if (!phandle)  		return -FDT_ERR_NOTFOUND; @@ -428,7 +439,7 @@ static int fdtdec_decode_gpios(const void *blob, int node,  	assert(max_count > 0);  	prop = fdt_get_property(blob, node, prop_name, &len);  	if (!prop) { -		debug("FDT: %s: property '%s' missing\n", __func__, prop_name); +		debug("%s: property '%s' missing\n", __func__, prop_name);  		return -FDT_ERR_NOTFOUND;  	} @@ -437,7 +448,7 @@ static int fdtdec_decode_gpios(const void *blob, int node,  	cell = (u32 *)prop->data;  	len /= sizeof(u32) * 3;		/* 3 cells per GPIO record */  	if (len > max_count) { -		debug("FDT: %s: too many GPIOs / cells for " +		debug(" %s: too many GPIOs / cells for "  			"property '%s'\n", __func__, prop_name);  		return -FDT_ERR_BADLAYOUT;  	} diff --git a/lib/hashtable.c b/lib/hashtable.c index abd61c891..670a704a4 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -142,7 +142,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) +void hdestroy_r(struct hsearch_data *htab, int do_apply)  {  	int i; @@ -156,7 +156,10 @@ void hdestroy_r(struct hsearch_data *htab)  	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);  		} @@ -401,7 +404,7 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,   * do that.   */ -int hdelete_r(const char *key, struct hsearch_data *htab) +int hdelete_r(const char *key, struct hsearch_data *htab, int do_apply)  {  	ENTRY e, *ep;  	int idx; @@ -417,7 +420,8 @@ int hdelete_r(const char *key, struct hsearch_data *htab)  	/* 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; @@ -604,6 +608,34 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,   */  /* + * Check whether variable 'name' is amongst vars[], + * and remove all instances by setting the pointer to NULL + */ +static int drop_var_from_set(const char *name, int nvars, char * vars[]) +{ +	int i = 0; +	int res = 0; + +	/* No variables specified means process all of them */ +	if (nvars == 0) +		return 1; + +	for (i = 0; i < nvars; i++) { +		if (vars[i] == NULL) +			continue; +		/* If we found it, delete all of them */ +		if (!strcmp(name, vars[i])) { +			vars[i] = NULL; +			res = 1; +		} +	} +	if (!res) +		debug("Skipping non-listed variable %s\n", name); + +	return res; +} + +/*   * Import linearized data into hash table.   *   * This is the inverse function to hexport(): it takes a linear list @@ -639,9 +671,12 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,   */  int himport_r(struct hsearch_data *htab, -	      const char *env, size_t size, const char sep, int flag) +		const char *env, size_t size, const char sep, int flag, +		int nvars, char * const vars[], int do_apply)  {  	char *data, *sp, *dp, *name, *value; +	char *localvars[nvars]; +	int i;  	/* Test for correct arguments.  */  	if (htab == NULL) { @@ -658,12 +693,16 @@ int himport_r(struct hsearch_data *htab,  	memcpy(data, env, size);  	dp = data; +	/* make a local copy of the list of variables */ +	if (nvars) +		memcpy(localvars, vars, sizeof(vars[0]) * nvars); +  	if ((flag & H_NOCLEAR) == 0) {  		/* Destroy old hash table if one exists */  		debug("Destroy Hash Table: %p table = %p\n", htab,  		       htab->table);  		if (htab->table) -			hdestroy_r(htab); +			hdestroy_r(htab, do_apply);  	}  	/* @@ -726,8 +765,10 @@ int himport_r(struct hsearch_data *htab,  			*dp++ = '\0';	/* terminate name */  			debug("DELETE CANDIDATE: \"%s\"\n", name); +			if (!drop_var_from_set(name, nvars, localvars)) +				continue; -			if (hdelete_r(name, htab) == 0) +			if (hdelete_r(name, htab, do_apply) == 0)  				debug("DELETE ERROR ##############################\n");  			continue; @@ -743,10 +784,32 @@ int himport_r(struct hsearch_data *htab,  		*sp++ = '\0';	/* terminate value */  		++dp; +		/* Skip variables which are not supposed to be processed */ +		if (!drop_var_from_set(name, nvars, localvars)) +			continue; +  		/* enter into hash table */  		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) {  			printf("himport_r: can't insert \"%s=%s\" into hash table\n", @@ -762,6 +825,24 @@ int himport_r(struct hsearch_data *htab,  	debug("INSERT: free(data = %p)\n", data);  	free(data); +	/* process variables which were not considered */ +	for (i = 0; i < nvars; i++) { +		if (localvars[i] == NULL) +			continue; +		/* +		 * All variables which were not deleted from the variable list +		 * were not present in the imported env +		 * This could mean two things: +		 * a) if the variable was present in current env, we delete it +		 * 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) +			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]); +	} +  	debug("INSERT: done\n");  	return 1;		/* everything OK */  } |