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