xref: /NextBSD/sys/boot/uboot/lib/glue.c (revision 287e3b14e9552995def1802ec9c5034f4adf28ec)
1 /*-
2  * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/types.h>
31 
32 #include <crc32.h>
33 #include <stand.h>
34 #include "api_public.h"
35 #include "glue.h"
36 
37 #ifdef DEBUG
38 #define	debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
39 #else
40 #define	debugf(fmt, args...)
41 #endif
42 
43 /* Some random address used by U-Boot. */
44 extern long uboot_address;
45 
46 static int
valid_sig(struct api_signature * sig)47 valid_sig(struct api_signature *sig)
48 {
49 	uint32_t checksum;
50 	struct api_signature s;
51 
52 	if (sig == NULL)
53 		return (0);
54 	/*
55 	 * Clear the checksum field (in the local copy) so as to calculate the
56 	 * CRC with the same initial contents as at the time when the sig was
57 	 * produced
58 	 */
59 	s = *sig;
60 	s.checksum = 0;
61 
62 	checksum = crc32((void *)&s, sizeof(struct api_signature));
63 
64 	if (checksum != sig->checksum)
65 		return (0);
66 
67 	return (1);
68 }
69 
70 /*
71  * Searches for the U-Boot API signature
72  *
73  * returns 1/0 depending on found/not found result
74  */
75 int
api_search_sig(struct api_signature ** sig)76 api_search_sig(struct api_signature **sig)
77 {
78 	unsigned char *sp, *spend;
79 
80 	if (sig == NULL)
81 		return (0);
82 
83 	if (uboot_address == 0)
84 		uboot_address = 255 * 1024 * 1024;
85 
86 	sp = (void *)(uboot_address & ~0x000fffff);
87 	spend = sp + 0x00300000 - API_SIG_MAGLEN;
88 	while (sp < spend) {
89 		if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
90 			*sig = (struct api_signature *)sp;
91 			if (valid_sig(*sig))
92 				return (1);
93 		}
94 		sp += API_SIG_MAGLEN;
95 	}
96 
97 	*sig = NULL;
98 	return (0);
99 }
100 
101 /****************************************
102  *
103  * console
104  *
105  ****************************************/
106 
107 int
ub_getc(void)108 ub_getc(void)
109 {
110 	int c;
111 
112 	if (!syscall(API_GETC, NULL, (uint32_t)&c))
113 		return (-1);
114 
115 	return (c);
116 }
117 
118 int
ub_tstc(void)119 ub_tstc(void)
120 {
121 	int t;
122 
123 	if (!syscall(API_TSTC, NULL, (uint32_t)&t))
124 		return (-1);
125 
126 	return (t);
127 }
128 
129 void
ub_putc(char c)130 ub_putc(char c)
131 {
132 
133 	syscall(API_PUTC, NULL, (uint32_t)&c);
134 }
135 
136 void
ub_puts(const char * s)137 ub_puts(const char *s)
138 {
139 
140 	syscall(API_PUTS, NULL, (uint32_t)s);
141 }
142 
143 /****************************************
144  *
145  * system
146  *
147  ****************************************/
148 
149 void
ub_reset(void)150 ub_reset(void)
151 {
152 
153 	syscall(API_RESET, NULL);
154 }
155 
156 static struct mem_region mr[UB_MAX_MR];
157 static struct sys_info si;
158 
159 struct sys_info *
ub_get_sys_info(void)160 ub_get_sys_info(void)
161 {
162 	int err = 0;
163 
164 	memset(&si, 0, sizeof(struct sys_info));
165 	si.mr = mr;
166 	si.mr_no = UB_MAX_MR;
167 	memset(&mr, 0, sizeof(mr));
168 
169 	if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si))
170 		return (NULL);
171 
172 	return ((err) ? NULL : &si);
173 }
174 
175 /****************************************
176  *
177  * timing
178  *
179  ****************************************/
180 
181 void
ub_udelay(unsigned long usec)182 ub_udelay(unsigned long usec)
183 {
184 
185 	syscall(API_UDELAY, NULL, &usec);
186 }
187 
188 unsigned long
ub_get_timer(unsigned long base)189 ub_get_timer(unsigned long base)
190 {
191 	unsigned long cur;
192 
193 	if (!syscall(API_GET_TIMER, NULL, &cur, &base))
194 		return (0);
195 
196 	return (cur);
197 }
198 
199 /****************************************************************************
200  *
201  * devices
202  *
203  * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
204  *
205  ***************************************************************************/
206 
207 static struct device_info devices[UB_MAX_DEV];
208 
209 struct device_info *
ub_dev_get(int i)210 ub_dev_get(int i)
211 {
212 
213 	return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
214 }
215 
216 /*
217  * Enumerates the devices: fills out device_info elements in the devices[]
218  * array.
219  *
220  * returns:		number of devices found
221  */
222 int
ub_dev_enum(void)223 ub_dev_enum(void)
224 {
225 	struct device_info *di;
226 	int n = 0;
227 
228 	memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
229 	di = &devices[0];
230 
231 	if (!syscall(API_DEV_ENUM, NULL, di))
232 		return (0);
233 
234 	while (di->cookie != NULL) {
235 
236 		if (++n >= UB_MAX_DEV)
237 			break;
238 
239 		/* take another device_info */
240 		di++;
241 
242 		/* pass on the previous cookie */
243 		di->cookie = devices[n - 1].cookie;
244 
245 		if (!syscall(API_DEV_ENUM, NULL, di))
246 			return (0);
247 	}
248 
249 	return (n);
250 }
251 
252 /*
253  * handle:	0-based id of the device
254  *
255  * returns:	0 when OK, err otherwise
256  */
257 int
ub_dev_open(int handle)258 ub_dev_open(int handle)
259 {
260 	struct device_info *di;
261 	int err = 0;
262 
263 	if (handle < 0 || handle >= UB_MAX_DEV)
264 		return (API_EINVAL);
265 
266 	di = &devices[handle];
267 	if (!syscall(API_DEV_OPEN, &err, di))
268 		return (-1);
269 
270 	return (err);
271 }
272 
273 int
ub_dev_close(int handle)274 ub_dev_close(int handle)
275 {
276 	struct device_info *di;
277 
278 	if (handle < 0 || handle >= UB_MAX_DEV)
279 		return (API_EINVAL);
280 
281 	di = &devices[handle];
282 	if (!syscall(API_DEV_CLOSE, NULL, di))
283 		return (-1);
284 
285 	return (0);
286 }
287 
288 /*
289  * Validates device for read/write, it has to:
290  *
291  * - have sane handle
292  * - be opened
293  *
294  * returns:	0/1 accordingly
295  */
296 static int
dev_valid(int handle)297 dev_valid(int handle)
298 {
299 
300 	if (handle < 0 || handle >= UB_MAX_DEV)
301 		return (0);
302 
303 	if (devices[handle].state != DEV_STA_OPEN)
304 		return (0);
305 
306 	return (1);
307 }
308 
309 static int
dev_stor_valid(int handle)310 dev_stor_valid(int handle)
311 {
312 
313 	if (!dev_valid(handle))
314 		return (0);
315 
316 	if (!(devices[handle].type & DEV_TYP_STOR))
317 		return (0);
318 
319 	return (1);
320 }
321 
322 int
ub_dev_read(int handle,void * buf,lbasize_t len,lbastart_t start,lbasize_t * rlen)323 ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
324     lbasize_t *rlen)
325 {
326 	struct device_info *di;
327 	lbasize_t act_len;
328 	int err = 0;
329 
330 	if (!dev_stor_valid(handle))
331 		return (API_ENODEV);
332 
333 	di = &devices[handle];
334 	if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
335 		return (API_ESYSC);
336 
337 	if (!err && rlen)
338 		*rlen = act_len;
339 
340 	return (err);
341 }
342 
343 static int
dev_net_valid(int handle)344 dev_net_valid(int handle)
345 {
346 
347 	if (!dev_valid(handle))
348 		return (0);
349 
350 	if (devices[handle].type != DEV_TYP_NET)
351 		return (0);
352 
353 	return (1);
354 }
355 
356 int
ub_dev_recv(int handle,void * buf,int len,int * rlen)357 ub_dev_recv(int handle, void *buf, int len, int *rlen)
358 {
359 	struct device_info *di;
360 	int err = 0, act_len;
361 
362 	if (!dev_net_valid(handle))
363 		return (API_ENODEV);
364 
365 	di = &devices[handle];
366 	if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
367 		return (API_ESYSC);
368 
369 	if (!err)
370 		*rlen = act_len;
371 
372 	return (err);
373 }
374 
375 int
ub_dev_send(int handle,void * buf,int len)376 ub_dev_send(int handle, void *buf, int len)
377 {
378 	struct device_info *di;
379 	int err = 0;
380 
381 	if (!dev_net_valid(handle))
382 		return (API_ENODEV);
383 
384 	di = &devices[handle];
385 	if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
386 		return (API_ESYSC);
387 
388 	return (err);
389 }
390 
391 char *
ub_stor_type(int type)392 ub_stor_type(int type)
393 {
394 
395 	if (type & DT_STOR_IDE)
396 		return ("IDE");
397 
398 	if (type & DT_STOR_SCSI)
399 		return ("SCSI");
400 
401 	if (type & DT_STOR_USB)
402 		return ("USB");
403 
404 	if (type & DT_STOR_MMC)
405 		return ("MMC");
406 
407 	if (type & DT_STOR_SATA)
408 		return ("SATA");
409 
410 	return ("Unknown");
411 }
412 
413 char *
ub_mem_type(int flags)414 ub_mem_type(int flags)
415 {
416 
417 	switch (flags & 0x000F) {
418 	case MR_ATTR_FLASH:
419 		return ("FLASH");
420 	case MR_ATTR_DRAM:
421 		return ("DRAM");
422 	case MR_ATTR_SRAM:
423 		return ("SRAM");
424 	default:
425 		return ("Unknown");
426 	}
427 }
428 
429 void
ub_dump_di(int handle)430 ub_dump_di(int handle)
431 {
432 	struct device_info *di = ub_dev_get(handle);
433 	int i;
434 
435 	printf("device info (%d):\n", handle);
436 	printf("  cookie\t= 0x%08x\n", (uint32_t)di->cookie);
437 	printf("  type\t\t= 0x%08x\n", di->type);
438 
439 	if (di->type == DEV_TYP_NET) {
440 		printf("  hwaddr\t= ");
441 		for (i = 0; i < 6; i++)
442 			printf("%02x ", di->di_net.hwaddr[i]);
443 
444 		printf("\n");
445 
446 	} else if (di->type & DEV_TYP_STOR) {
447 		printf("  type\t\t= %s\n", ub_stor_type(di->type));
448 		printf("  blk size\t\t= %ld\n", di->di_stor.block_size);
449 		printf("  blk count\t\t= %ld\n", di->di_stor.block_count);
450 	}
451 }
452 
453 void
ub_dump_si(struct sys_info * si)454 ub_dump_si(struct sys_info *si)
455 {
456 	int i;
457 
458 	printf("sys info:\n");
459 	printf("  clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000);
460 	printf("  clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000);
461 	printf("  bar\t\t= 0x%08lx\n", si->bar);
462 
463 	printf("---\n");
464 	for (i = 0; i < si->mr_no; i++) {
465 		if (si->mr[i].flags == 0)
466 			break;
467 
468 		printf("  start\t= 0x%08lx\n", si->mr[i].start);
469 		printf("  size\t= 0x%08lx\n", si->mr[i].size);
470 		printf("  type\t= %s\n", ub_mem_type(si->mr[i].flags));
471 		printf("---\n");
472 	}
473 }
474 
475 /****************************************
476  *
477  * env vars
478  *
479  ****************************************/
480 
481 char *
ub_env_get(const char * name)482 ub_env_get(const char *name)
483 {
484 	char *value;
485 
486 	if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value))
487 		return (NULL);
488 
489 	return (value);
490 }
491 
492 void
ub_env_set(const char * name,char * value)493 ub_env_set(const char *name, char *value)
494 {
495 
496 	syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value);
497 }
498 
499 static char env_name[256];
500 
501 const char *
ub_env_enum(const char * last)502 ub_env_enum(const char *last)
503 {
504 	const char *env, *str;
505 	int i;
506 
507 	/*
508 	 * It's OK to pass only the name piece as last (and not the whole
509 	 * 'name=val' string), since the API_ENUM_ENV call uses envmatch()
510 	 * internally, which handles such case
511 	 */
512 	env = NULL;
513 	if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env))
514 		return (NULL);
515 
516 	if (env == NULL || last == env)
517 		/* no more env. variables to enumerate */
518 		return (NULL);
519 
520 	/* next enumerated env var */
521 	memset(env_name, 0, 256);
522 	for (i = 0, str = env; *str != '=' && *str != '\0';)
523 		env_name[i++] = *str++;
524 
525 	env_name[i] = '\0';
526 
527 	return (env_name);
528 }
529