Blame view

env/callback.c 3.22 KB
170ab1107   Joe Hershberger   env: Add support ...
1
2
3
4
  /*
   * (C) Copyright 2012
   * Joe Hershberger, National Instruments, joe.hershberger@ni.com
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
5
   * SPDX-License-Identifier:	GPL-2.0+
170ab1107   Joe Hershberger   env: Add support ...
6
7
8
9
10
11
12
13
14
15
16
17
   */
  
  #include <common.h>
  #include <environment.h>
  
  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  DECLARE_GLOBAL_DATA_PTR;
  #endif
  
  /*
   * Look up a callback function pointer by name
   */
268d966df   Tom Rini   env_callback: Mar...
18
  static struct env_clbk_tbl *find_env_callback(const char *name)
170ab1107   Joe Hershberger   env: Add support ...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  {
  	struct env_clbk_tbl *clbkp;
  	int i;
  	int num_callbacks = ll_entry_count(struct env_clbk_tbl, env_clbk);
  
  	if (name == NULL)
  		return NULL;
  
  	/* look up the callback in the linker-list */
  	for (i = 0, clbkp = ll_entry_start(struct env_clbk_tbl, env_clbk);
  	     i < num_callbacks;
  	     i++, clbkp++) {
  		if (strcmp(name, clbkp->name) == 0)
  			return clbkp;
  	}
  
  	return NULL;
  }
1b6102718   Heiko Schocher   common, env: opti...
37
38
  static int first_call = 1;
  static const char *callback_list;
170ab1107   Joe Hershberger   env: Add support ...
39
40
41
42
43
44
45
46
  /*
   * Look for a possible callback for a newly added variable
   * This is called specifically when the variable did not exist in the hash
   * previously, so the blanket update did not find this variable.
   */
  void env_callback_init(ENTRY *var_entry)
  {
  	const char *var_name = var_entry->key;
170ab1107   Joe Hershberger   env: Add support ...
47
48
49
  	char callback_name[256] = "";
  	struct env_clbk_tbl *clbkp;
  	int ret = 1;
1b6102718   Heiko Schocher   common, env: opti...
50
  	if (first_call) {
00caae6d4   Simon Glass   env: Rename geten...
51
  		callback_list = env_get(ENV_CALLBACK_VAR);
1b6102718   Heiko Schocher   common, env: opti...
52
53
  		first_call = 0;
  	}
170ab1107   Joe Hershberger   env: Add support ...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  	/* look in the ".callbacks" var for a reference to this variable */
  	if (callback_list != NULL)
  		ret = env_attr_lookup(callback_list, var_name, callback_name);
  
  	/* only if not found there, look in the static list */
  	if (ret)
  		ret = env_attr_lookup(ENV_CALLBACK_LIST_STATIC, var_name,
  			callback_name);
  
  	/* if an association was found, set the callback pointer */
  	if (!ret && strlen(callback_name)) {
  		clbkp = find_env_callback(callback_name);
  		if (clbkp != NULL)
  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  			var_entry->callback = clbkp->callback + gd->reloc_off;
  #else
  			var_entry->callback = clbkp->callback;
  #endif
  	}
  }
  
  /*
   * Called on each existing env var prior to the blanket update since removing
   * a callback association should remove its callback.
   */
  static int clear_callback(ENTRY *entry)
  {
  	entry->callback = NULL;
  
  	return 0;
  }
  
  /*
   * Call for each element in the list that associates variables to callbacks
   */
cca98fd6a   Joe Hershberger   env: Allow env_at...
89
  static int set_callback(const char *name, const char *value, void *priv)
170ab1107   Joe Hershberger   env: Add support ...
90
91
92
93
94
95
  {
  	ENTRY e, *ep;
  	struct env_clbk_tbl *clbkp;
  
  	e.key	= name;
  	e.data	= NULL;
5a6894397   Peng Fan   common: env: init...
96
  	e.callback = NULL;
170ab1107   Joe Hershberger   env: Add support ...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  	hsearch_r(e, FIND, &ep, &env_htab, 0);
  
  	/* does the env variable actually exist? */
  	if (ep != NULL) {
  		/* the assocaition delares no callback, so remove the pointer */
  		if (value == NULL || strlen(value) == 0)
  			ep->callback = NULL;
  		else {
  			/* assign the requested callback */
  			clbkp = find_env_callback(value);
  			if (clbkp != NULL)
  #if defined(CONFIG_NEEDS_MANUAL_RELOC)
  				ep->callback = clbkp->callback + gd->reloc_off;
  #else
  				ep->callback = clbkp->callback;
  #endif
  		}
  	}
  
  	return 0;
  }
  
  static int on_callbacks(const char *name, const char *value, enum env_op op,
  	int flags)
  {
  	/* remove all callbacks */
  	hwalk_r(&env_htab, clear_callback);
  
  	/* configure any static callback bindings */
cca98fd6a   Joe Hershberger   env: Allow env_at...
126
  	env_attr_walk(ENV_CALLBACK_LIST_STATIC, set_callback, NULL);
170ab1107   Joe Hershberger   env: Add support ...
127
  	/* configure any dynamic callback bindings */
cca98fd6a   Joe Hershberger   env: Allow env_at...
128
  	env_attr_walk(value, set_callback, NULL);
170ab1107   Joe Hershberger   env: Add support ...
129
130
131
132
  
  	return 0;
  }
  U_BOOT_ENV_CALLBACK(callbacks, on_callbacks);