2 * Copyright (c) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/types.h>
31 #include "api_public.h"
35 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
37 #define debugf(fmt, args...)
40 /* Some random address used by U-Boot. */
41 extern long uboot_address;
44 valid_sig(struct api_signature *sig)
47 struct api_signature s;
52 * Clear the checksum field (in the local copy) so as to calculate the
53 * CRC with the same initial contents as at the time when the sig was
57 s.checksum = crc32(0, Z_NULL, 0);
59 checksum = crc32(s.checksum, (void *)&s, sizeof(struct api_signature));
61 if (checksum != sig->checksum)
68 * Checks to see if API signature's address was given to us as a command line
71 * returns 1/0 depending on found/not found result
74 api_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig)
76 unsigned long api_address;
84 while ((c = getopt (argc, argv, "a:")) != -1)
87 api_address = strtoul(optarg, NULL, 16);
93 if (api_address != 0) {
94 *sig = (struct api_signature *)api_address;
103 * Searches for the U-Boot API signature
105 * returns 1/0 depending on found/not found result
108 api_search_sig(struct api_signature **sig)
110 unsigned char *sp, *spend;
115 if (uboot_address == 0)
116 uboot_address = 255 * 1024 * 1024;
118 sp = (void *)(uboot_address & API_SIG_SEARCH_MASK);
119 spend = sp + API_SIG_SEARCH_LEN - API_SIG_MAGLEN;
122 if (!bcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
123 *sig = (struct api_signature *)sp;
127 sp += API_SIG_MAGLEN;
134 /****************************************
138 ****************************************/
145 if (!syscall(API_GETC, NULL, &c))
156 if (!syscall(API_TSTC, NULL, &t))
163 ub_putc(const char c)
166 syscall(API_PUTC, NULL, &c);
170 ub_puts(const char *s)
173 syscall(API_PUTS, NULL, s);
176 /****************************************
180 ****************************************/
186 syscall(API_RESET, NULL);
187 while (1); /* fallback if API_RESET failed */
191 static struct mem_region mr[UB_MAX_MR];
192 static struct sys_info si;
195 ub_get_sys_info(void)
199 memset(&si, 0, sizeof(struct sys_info));
201 si.mr_no = UB_MAX_MR;
202 memset(&mr, 0, sizeof(mr));
204 if (!syscall(API_GET_SYS_INFO, &err, &si))
207 return ((err) ? NULL : &si);
210 /****************************************
214 ****************************************/
217 ub_udelay(unsigned long usec)
220 syscall(API_UDELAY, NULL, &usec);
224 ub_get_timer(unsigned long base)
228 if (!syscall(API_GET_TIMER, NULL, &cur, &base))
234 /****************************************************************************
238 * Devices are identified by handles: numbers 0, 1, 2, ..., UB_MAX_DEV-1
240 ***************************************************************************/
242 static struct device_info devices[UB_MAX_DEV];
248 return ((i < 0 || i >= UB_MAX_DEV) ? NULL : &devices[i]);
252 * Enumerates the devices: fills out device_info elements in the devices[]
255 * returns: number of devices found
260 struct device_info *di;
263 memset(&devices, 0, sizeof(struct device_info) * UB_MAX_DEV);
266 if (!syscall(API_DEV_ENUM, NULL, di))
269 while (di->cookie != NULL) {
271 if (++n >= UB_MAX_DEV)
274 /* take another device_info */
277 /* pass on the previous cookie */
278 di->cookie = devices[n - 1].cookie;
280 if (!syscall(API_DEV_ENUM, NULL, di))
288 * handle: 0-based id of the device
290 * returns: 0 when OK, err otherwise
293 ub_dev_open(int handle)
295 struct device_info *di;
298 if (handle < 0 || handle >= UB_MAX_DEV)
301 di = &devices[handle];
302 if (!syscall(API_DEV_OPEN, &err, di))
309 ub_dev_close(int handle)
311 struct device_info *di;
313 if (handle < 0 || handle >= UB_MAX_DEV)
316 di = &devices[handle];
317 if (!syscall(API_DEV_CLOSE, NULL, di))
324 * Validates device for read/write, it has to:
329 * returns: 0/1 accordingly
332 dev_valid(int handle)
335 if (handle < 0 || handle >= UB_MAX_DEV)
338 if (devices[handle].state != DEV_STA_OPEN)
345 dev_stor_valid(int handle)
348 if (!dev_valid(handle))
351 if (!(devices[handle].type & DEV_TYP_STOR))
358 ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start,
361 struct device_info *di;
365 if (!dev_stor_valid(handle))
368 di = &devices[handle];
369 if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
379 dev_net_valid(int handle)
382 if (!dev_valid(handle))
385 if (devices[handle].type != DEV_TYP_NET)
392 ub_dev_recv(int handle, void *buf, int len, int *rlen)
394 struct device_info *di;
395 int err = 0, act_len;
397 if (!dev_net_valid(handle))
400 di = &devices[handle];
401 if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
411 ub_dev_send(int handle, void *buf, int len)
413 struct device_info *di;
416 if (!dev_net_valid(handle))
419 di = &devices[handle];
420 if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
427 ub_stor_type(int type)
430 if (type & DT_STOR_IDE)
433 if (type & DT_STOR_SCSI)
436 if (type & DT_STOR_USB)
439 if (type & DT_STOR_MMC)
442 if (type & DT_STOR_SATA)
449 ub_mem_type(int flags)
452 switch (flags & 0x000F) {
465 ub_dump_di(int handle)
467 struct device_info *di = ub_dev_get(handle);
470 printf("device info (%d):\n", handle);
471 printf(" cookie\t= %p\n", di->cookie);
472 printf(" type\t\t= 0x%08x\n", di->type);
474 if (di->type == DEV_TYP_NET) {
475 printf(" hwaddr\t= ");
476 for (i = 0; i < 6; i++)
477 printf("%02x ", di->di_net.hwaddr[i]);
481 } else if (di->type & DEV_TYP_STOR) {
482 printf(" type\t\t= %s\n", ub_stor_type(di->type));
483 printf(" blk size\t\t= %ld\n", di->di_stor.block_size);
484 printf(" blk count\t\t= %ld\n", di->di_stor.block_count);
489 ub_dump_si(struct sys_info *si)
493 printf("sys info:\n");
494 printf(" clkbus\t= %ld MHz\n", si->clk_bus / 1000 / 1000);
495 printf(" clkcpu\t= %ld MHz\n", si->clk_cpu / 1000 / 1000);
496 printf(" bar\t\t= 0x%08lx\n", si->bar);
499 for (i = 0; i < si->mr_no; i++) {
500 if (si->mr[i].flags == 0)
503 printf(" start\t= 0x%08lx\n", si->mr[i].start);
504 printf(" size\t= 0x%08lx\n", si->mr[i].size);
505 printf(" type\t= %s\n", ub_mem_type(si->mr[i].flags));
510 /****************************************
514 ****************************************/
517 ub_env_get(const char *name)
521 if (!syscall(API_ENV_GET, NULL, name, &value))
528 ub_env_set(const char *name, char *value)
531 syscall(API_ENV_SET, NULL, name, value);
534 static char env_name[256];
537 ub_env_enum(const char *last)
539 const char *env, *str;
543 * It's OK to pass only the name piece as last (and not the whole
544 * 'name=val' string), since the API_ENUM_ENV call uses envmatch()
545 * internally, which handles such case
548 if (!syscall(API_ENV_ENUM, NULL, last, &env))
551 if (env == NULL || last == env)
552 /* no more env. variables to enumerate */
555 /* next enumerated env var */
556 memset(env_name, 0, 256);
557 for (i = 0, str = env; *str != '=' && *str != '\0';)
558 env_name[i++] = *str++;