]>
Commit | Line | Data |
---|---|---|
500856eb RJ |
1 | /* |
2 | * (C) Copyright 2007 Semihalf | |
3 | * | |
4 | * Written by: Rafal Jaworowski <raj@semihalf.com> | |
5 | * | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License as | |
11 | * published by the Free Software Foundation; either version 2 of | |
12 | * the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
22 | * MA 02111-1307 USA | |
23 | * | |
24 | */ | |
25 | ||
26 | #include <common.h> | |
27 | #include <linux/types.h> | |
28 | #include <api_public.h> | |
29 | ||
30 | #include "glue.h" | |
31 | ||
32 | static int valid_sig(struct api_signature *sig) | |
33 | { | |
34 | uint32_t checksum; | |
35 | struct api_signature s; | |
36 | ||
37 | if (sig == NULL) | |
38 | return 0; | |
39 | /* | |
40 | * Clear the checksum field (in the local copy) so as to calculate the | |
41 | * CRC with the same initial contents as at the time when the sig was | |
42 | * produced | |
43 | */ | |
44 | s = *sig; | |
45 | s.checksum = 0; | |
46 | ||
47 | checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature)); | |
48 | ||
49 | if (checksum != sig->checksum) | |
50 | return 0; | |
51 | ||
52 | return 1; | |
53 | } | |
54 | ||
55 | /* | |
56 | * Searches for the U-Boot API signature | |
57 | * | |
58 | * returns 1/0 depending on found/not found result | |
59 | */ | |
60 | int api_search_sig(struct api_signature **sig) { | |
61 | ||
62 | unsigned char *sp; | |
63 | ||
64 | if (sig == NULL) | |
65 | return 0; | |
66 | ||
67 | sp = (unsigned char *)API_SEARCH_START; | |
68 | ||
69 | while ((sp + (int)API_SIG_MAGLEN) < (unsigned char *)API_SEARCH_END) { | |
70 | if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) { | |
71 | *sig = (struct api_signature *)sp; | |
72 | if (valid_sig(*sig)) | |
73 | return 1; | |
74 | } | |
75 | sp += API_SIG_MAGLEN; | |
76 | } | |
77 | ||
78 | *sig = NULL; | |
79 | return 0; | |
80 | } | |
81 | ||
82 | /**************************************** | |
83 | * | |
84 | * console | |
85 | * | |
86 | ****************************************/ | |
87 | ||
88 | int ub_getc(void) | |
89 | { | |
90 | int c; | |
91 | ||
92 | if (!syscall(API_GETC, NULL, (uint32_t)&c)) | |
93 | return -1; | |
94 | ||
95 | return c; | |
96 | } | |
97 | ||
98 | int ub_tstc(void) | |
99 | { | |
100 | int t; | |
101 | ||
102 | if (!syscall(API_TSTC, NULL, (uint32_t)&t)) | |
103 | return -1; | |
104 | ||
105 | return t; | |
106 | } | |
107 | ||
108 | void ub_putc(char c) | |
109 | { | |
110 | syscall(API_PUTC, NULL, (uint32_t)&c); | |
111 | } | |
112 | ||
113 | void ub_puts(const char *s) | |
114 | { | |
115 | syscall(API_PUTS, NULL, (uint32_t)s); | |
116 | } | |
117 | ||
118 | /**************************************** | |
119 | * | |
120 | * system | |
121 | * | |
122 | ****************************************/ | |
123 | ||
124 | void ub_reset(void) | |
125 | { | |
126 | syscall(API_RESET, NULL); | |
127 | } | |
128 | ||
129 | #define MR_MAX 5 | |
130 | static struct mem_region mr[MR_MAX]; | |
131 | static struct sys_info si; | |
132 | ||
133 | struct sys_info * ub_get_sys_info(void) | |
134 | { | |
135 | int err = 0; | |
136 | ||
137 | memset(&si, 0, sizeof(struct sys_info)); | |
138 | si.mr = mr; | |
139 | si.mr_no = MR_MAX; | |
140 | memset(&mr, 0, sizeof(mr)); | |
141 | ||
142 | if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si)) | |
143 | return NULL; | |
144 | ||
145 | return ((err) ? NULL : &si); | |
146 | } | |
147 | ||
148 | /**************************************** | |
149 | * | |
150 | * timing | |
151 | * | |
152 | ****************************************/ | |
d3a6532c | 153 | |
500856eb RJ |
154 | void ub_udelay(unsigned long usec) |
155 | { | |
156 | syscall(API_UDELAY, NULL, &usec); | |
157 | } | |
158 | ||
159 | unsigned long ub_get_timer(unsigned long base) | |
160 | { | |
161 | unsigned long cur; | |
162 | ||
163 | if (!syscall(API_GET_TIMER, NULL, &cur, &base)) | |
164 | return 0; | |
165 | ||
166 | return cur; | |
167 | } | |
168 | ||
169 | ||
170 | /**************************************************************************** | |
171 | * | |
172 | * devices | |
173 | * | |
174 | * Devices are identified by handles: numbers 0, 1, 2, ..., MAX_DEVS-1 | |
175 | * | |
176 | ***************************************************************************/ | |
177 | ||
178 | #define MAX_DEVS 6 | |
179 | ||
180 | static struct device_info devices[MAX_DEVS]; | |
181 | ||
182 | struct device_info * ub_dev_get(int i) | |
183 | { | |
184 | return ((i < 0 || i >= MAX_DEVS) ? NULL : &devices[i]); | |
185 | } | |
186 | ||
187 | /* | |
188 | * Enumerates the devices: fills out device_info elements in the devices[] | |
189 | * array. | |
190 | * | |
191 | * returns: number of devices found | |
192 | */ | |
193 | int ub_dev_enum(void) | |
194 | { | |
195 | struct device_info *di; | |
196 | int n = 0; | |
197 | ||
198 | memset(&devices, 0, sizeof(struct device_info) * MAX_DEVS); | |
199 | di = &devices[0]; | |
200 | ||
201 | if (!syscall(API_DEV_ENUM, NULL, di)) | |
202 | return 0; | |
203 | ||
204 | while (di->cookie != NULL) { | |
205 | ||
206 | if (++n >= MAX_DEVS) | |
207 | break; | |
208 | ||
209 | /* take another device_info */ | |
210 | di++; | |
211 | ||
212 | /* pass on the previous cookie */ | |
213 | di->cookie = devices[n - 1].cookie; | |
214 | ||
215 | if (!syscall(API_DEV_ENUM, NULL, di)) | |
216 | return 0; | |
217 | } | |
218 | ||
219 | return n; | |
220 | } | |
221 | ||
222 | /* | |
223 | * handle: 0-based id of the device | |
224 | * | |
225 | * returns: 0 when OK, err otherwise | |
226 | */ | |
227 | int ub_dev_open(int handle) | |
228 | { | |
229 | struct device_info *di; | |
230 | int err = 0; | |
231 | ||
232 | if (handle < 0 || handle >= MAX_DEVS) | |
233 | return API_EINVAL; | |
234 | ||
235 | di = &devices[handle]; | |
236 | ||
237 | if (!syscall(API_DEV_OPEN, &err, di)) | |
238 | return -1; | |
239 | ||
240 | return err; | |
241 | } | |
242 | ||
243 | int ub_dev_close(int handle) | |
244 | { | |
245 | struct device_info *di; | |
246 | ||
247 | if (handle < 0 || handle >= MAX_DEVS) | |
248 | return API_EINVAL; | |
249 | ||
250 | di = &devices[handle]; | |
251 | if (!syscall(API_DEV_CLOSE, NULL, di)) | |
252 | return -1; | |
253 | ||
254 | return 0; | |
255 | } | |
256 | ||
257 | /* | |
258 | * | |
259 | * Validates device for read/write, it has to: | |
260 | * | |
261 | * - have sane handle | |
262 | * - be opened | |
263 | * | |
264 | * returns: 0/1 accordingly | |
265 | */ | |
266 | static int dev_valid(int handle) | |
267 | { | |
268 | if (handle < 0 || handle >= MAX_DEVS) | |
269 | return 0; | |
270 | ||
271 | if (devices[handle].state != DEV_STA_OPEN) | |
272 | return 0; | |
273 | ||
274 | return 1; | |
275 | } | |
276 | ||
277 | static int dev_stor_valid(int handle) | |
278 | { | |
279 | if (!dev_valid(handle)) | |
280 | return 0; | |
281 | ||
282 | if (!(devices[handle].type & DEV_TYP_STOR)) | |
283 | return 0; | |
284 | ||
285 | return 1; | |
286 | } | |
287 | ||
288 | int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start) | |
289 | { | |
290 | struct device_info *di; | |
291 | lbasize_t act_len; | |
292 | int err = 0; | |
293 | ||
294 | if (!dev_stor_valid(handle)) | |
295 | return API_ENODEV; | |
296 | ||
297 | di = &devices[handle]; | |
298 | if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len)) | |
299 | return -1; | |
300 | ||
d3a6532c | 301 | if (err) |
500856eb RJ |
302 | return err; |
303 | ||
304 | if (act_len != len) | |
305 | return API_EIO; | |
306 | ||
307 | return 0; | |
308 | } | |
309 | ||
310 | static int dev_net_valid(int handle) | |
311 | { | |
312 | if (!dev_valid(handle)) | |
313 | return 0; | |
314 | ||
315 | if (devices[handle].type != DEV_TYP_NET) | |
316 | return 0; | |
317 | ||
318 | return 1; | |
319 | } | |
320 | ||
321 | int ub_dev_recv(int handle, void *buf, int len) | |
322 | { | |
323 | struct device_info *di; | |
324 | int err = 0, act_len; | |
325 | ||
326 | if (!dev_net_valid(handle)) | |
327 | return API_ENODEV; | |
328 | ||
329 | di = &devices[handle]; | |
330 | if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len)) | |
331 | return -1; | |
332 | ||
333 | if (err) | |
334 | return -1; | |
335 | ||
336 | return act_len; | |
337 | } | |
338 | ||
339 | int ub_dev_send(int handle, void *buf, int len) | |
340 | { | |
341 | struct device_info *di; | |
342 | int err = 0; | |
343 | ||
344 | if (!dev_net_valid(handle)) | |
345 | return API_ENODEV; | |
346 | ||
347 | di = &devices[handle]; | |
348 | if (!syscall(API_DEV_WRITE, &err, di, buf, &len)) | |
349 | return -1; | |
350 | ||
351 | return err; | |
352 | } | |
353 | ||
354 | /**************************************** | |
355 | * | |
356 | * env vars | |
357 | * | |
358 | ****************************************/ | |
359 | ||
360 | char * ub_env_get(const char *name) | |
361 | { | |
362 | char *value; | |
363 | ||
364 | if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value)) | |
365 | return NULL; | |
366 | ||
367 | return value; | |
368 | } | |
369 | ||
370 | void ub_env_set(const char *name, char *value) | |
371 | { | |
372 | syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value); | |
373 | } | |
374 | ||
375 | ||
376 | static char env_name[256]; | |
377 | ||
378 | const char * ub_env_enum(const char *last) | |
379 | { | |
380 | const char *env, *str; | |
381 | int i; | |
382 | ||
383 | env = NULL; | |
384 | ||
385 | /* | |
386 | * It's OK to pass only the name piece as last (and not the whole | |
387 | * 'name=val' string), since the API_ENUM_ENV call uses envmatch() | |
388 | * internally, which handles such case | |
389 | */ | |
390 | if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env)) | |
391 | return NULL; | |
392 | ||
393 | if (!env) | |
394 | /* no more env. variables to enumerate */ | |
395 | return NULL; | |
396 | ||
397 | /* next enumerated env var */ | |
398 | memset(env_name, 0, 256); | |
399 | for (i = 0, str = env; *str != '=' && *str != '\0';) | |
400 | env_name[i++] = *str++; | |
401 | ||
402 | env_name[i] = '\0'; | |
403 | ||
404 | return env_name; | |
405 | } |