glue.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. #include <common.h>
  26. #include <linux/types.h>
  27. #include <api_public.h>
  28. #include "glue.h"
  29. static int valid_sig(struct api_signature *sig)
  30. {
  31. uint32_t checksum;
  32. struct api_signature s;
  33. if (sig == NULL)
  34. return 0;
  35. /*
  36. * Clear the checksum field (in the local copy) so as to calculate the
  37. * CRC with the same initial contents as at the time when the sig was
  38. * produced
  39. */
  40. s = *sig;
  41. s.checksum = 0;
  42. checksum = crc32(0, (unsigned char *)&s, sizeof(struct api_signature));
  43. if (checksum != sig->checksum)
  44. return 0;
  45. return 1;
  46. }
  47. /*
  48. * Searches for the U-Boot API signature
  49. *
  50. * returns 1/0 depending on found/not found result
  51. */
  52. int api_search_sig(struct api_signature **sig) {
  53. unsigned char *sp;
  54. uint32_t search_start = 0;
  55. uint32_t search_end = 0;
  56. if (sig == NULL)
  57. return 0;
  58. if (search_hint == 0)
  59. search_hint = 255 * 1024 * 1024;
  60. search_start = search_hint & ~0x000fffff;
  61. search_end = search_start + API_SEARCH_LEN - API_SIG_MAGLEN;
  62. sp = (unsigned char *)search_start;
  63. while ((sp + API_SIG_MAGLEN) < (unsigned char *)search_end) {
  64. if (!memcmp(sp, API_SIG_MAGIC, API_SIG_MAGLEN)) {
  65. *sig = (struct api_signature *)sp;
  66. if (valid_sig(*sig))
  67. return 1;
  68. }
  69. sp += API_SIG_MAGLEN;
  70. }
  71. *sig = NULL;
  72. return 0;
  73. }
  74. /****************************************
  75. *
  76. * console
  77. *
  78. ****************************************/
  79. int ub_getc(void)
  80. {
  81. int c;
  82. if (!syscall(API_GETC, NULL, (uint32_t)&c))
  83. return -1;
  84. return c;
  85. }
  86. int ub_tstc(void)
  87. {
  88. int t;
  89. if (!syscall(API_TSTC, NULL, (uint32_t)&t))
  90. return -1;
  91. return t;
  92. }
  93. void ub_putc(char c)
  94. {
  95. syscall(API_PUTC, NULL, (uint32_t)&c);
  96. }
  97. void ub_puts(const char *s)
  98. {
  99. syscall(API_PUTS, NULL, (uint32_t)s);
  100. }
  101. /****************************************
  102. *
  103. * system
  104. *
  105. ****************************************/
  106. void ub_reset(void)
  107. {
  108. syscall(API_RESET, NULL);
  109. }
  110. #define MR_MAX 5
  111. static struct mem_region mr[MR_MAX];
  112. static struct sys_info si;
  113. struct sys_info * ub_get_sys_info(void)
  114. {
  115. int err = 0;
  116. memset(&si, 0, sizeof(struct sys_info));
  117. si.mr = mr;
  118. si.mr_no = MR_MAX;
  119. memset(&mr, 0, sizeof(mr));
  120. if (!syscall(API_GET_SYS_INFO, &err, (u_int32_t)&si))
  121. return NULL;
  122. return ((err) ? NULL : &si);
  123. }
  124. /****************************************
  125. *
  126. * timing
  127. *
  128. ****************************************/
  129. void ub_udelay(unsigned long usec)
  130. {
  131. syscall(API_UDELAY, NULL, &usec);
  132. }
  133. unsigned long ub_get_timer(unsigned long base)
  134. {
  135. unsigned long cur;
  136. if (!syscall(API_GET_TIMER, NULL, &cur, &base))
  137. return 0;
  138. return cur;
  139. }
  140. /****************************************************************************
  141. *
  142. * devices
  143. *
  144. * Devices are identified by handles: numbers 0, 1, 2, ..., MAX_DEVS-1
  145. *
  146. ***************************************************************************/
  147. #define MAX_DEVS 6
  148. static struct device_info devices[MAX_DEVS];
  149. struct device_info * ub_dev_get(int i)
  150. {
  151. return ((i < 0 || i >= MAX_DEVS) ? NULL : &devices[i]);
  152. }
  153. /*
  154. * Enumerates the devices: fills out device_info elements in the devices[]
  155. * array.
  156. *
  157. * returns: number of devices found
  158. */
  159. int ub_dev_enum(void)
  160. {
  161. struct device_info *di;
  162. int n = 0;
  163. memset(&devices, 0, sizeof(struct device_info) * MAX_DEVS);
  164. di = &devices[0];
  165. if (!syscall(API_DEV_ENUM, NULL, di))
  166. return 0;
  167. while (di->cookie != NULL) {
  168. if (++n >= MAX_DEVS)
  169. break;
  170. /* take another device_info */
  171. di++;
  172. /* pass on the previous cookie */
  173. di->cookie = devices[n - 1].cookie;
  174. if (!syscall(API_DEV_ENUM, NULL, di))
  175. return 0;
  176. }
  177. return n;
  178. }
  179. /*
  180. * handle: 0-based id of the device
  181. *
  182. * returns: 0 when OK, err otherwise
  183. */
  184. int ub_dev_open(int handle)
  185. {
  186. struct device_info *di;
  187. int err = 0;
  188. if (handle < 0 || handle >= MAX_DEVS)
  189. return API_EINVAL;
  190. di = &devices[handle];
  191. if (!syscall(API_DEV_OPEN, &err, di))
  192. return -1;
  193. return err;
  194. }
  195. int ub_dev_close(int handle)
  196. {
  197. struct device_info *di;
  198. if (handle < 0 || handle >= MAX_DEVS)
  199. return API_EINVAL;
  200. di = &devices[handle];
  201. if (!syscall(API_DEV_CLOSE, NULL, di))
  202. return -1;
  203. return 0;
  204. }
  205. /*
  206. *
  207. * Validates device for read/write, it has to:
  208. *
  209. * - have sane handle
  210. * - be opened
  211. *
  212. * returns: 0/1 accordingly
  213. */
  214. static int dev_valid(int handle)
  215. {
  216. if (handle < 0 || handle >= MAX_DEVS)
  217. return 0;
  218. if (devices[handle].state != DEV_STA_OPEN)
  219. return 0;
  220. return 1;
  221. }
  222. static int dev_stor_valid(int handle)
  223. {
  224. if (!dev_valid(handle))
  225. return 0;
  226. if (!(devices[handle].type & DEV_TYP_STOR))
  227. return 0;
  228. return 1;
  229. }
  230. int ub_dev_read(int handle, void *buf, lbasize_t len, lbastart_t start)
  231. {
  232. struct device_info *di;
  233. lbasize_t act_len;
  234. int err = 0;
  235. if (!dev_stor_valid(handle))
  236. return API_ENODEV;
  237. di = &devices[handle];
  238. if (!syscall(API_DEV_READ, &err, di, buf, &len, &start, &act_len))
  239. return -1;
  240. if (err)
  241. return err;
  242. if (act_len != len)
  243. return API_EIO;
  244. return 0;
  245. }
  246. static int dev_net_valid(int handle)
  247. {
  248. if (!dev_valid(handle))
  249. return 0;
  250. if (devices[handle].type != DEV_TYP_NET)
  251. return 0;
  252. return 1;
  253. }
  254. int ub_dev_recv(int handle, void *buf, int len)
  255. {
  256. struct device_info *di;
  257. int err = 0, act_len;
  258. if (!dev_net_valid(handle))
  259. return API_ENODEV;
  260. di = &devices[handle];
  261. if (!syscall(API_DEV_READ, &err, di, buf, &len, &act_len))
  262. return -1;
  263. if (err)
  264. return -1;
  265. return act_len;
  266. }
  267. int ub_dev_send(int handle, void *buf, int len)
  268. {
  269. struct device_info *di;
  270. int err = 0;
  271. if (!dev_net_valid(handle))
  272. return API_ENODEV;
  273. di = &devices[handle];
  274. if (!syscall(API_DEV_WRITE, &err, di, buf, &len))
  275. return -1;
  276. return err;
  277. }
  278. /****************************************
  279. *
  280. * env vars
  281. *
  282. ****************************************/
  283. char * ub_env_get(const char *name)
  284. {
  285. char *value;
  286. if (!syscall(API_ENV_GET, NULL, (uint32_t)name, (uint32_t)&value))
  287. return NULL;
  288. return value;
  289. }
  290. void ub_env_set(const char *name, char *value)
  291. {
  292. syscall(API_ENV_SET, NULL, (uint32_t)name, (uint32_t)value);
  293. }
  294. static char env_name[256];
  295. const char * ub_env_enum(const char *last)
  296. {
  297. const char *env, *str;
  298. int i;
  299. env = NULL;
  300. /*
  301. * It's OK to pass only the name piece as last (and not the whole
  302. * 'name=val' string), since the API_ENUM_ENV call uses envmatch()
  303. * internally, which handles such case
  304. */
  305. if (!syscall(API_ENV_ENUM, NULL, (uint32_t)last, (uint32_t)&env))
  306. return NULL;
  307. if (!env)
  308. /* no more env. variables to enumerate */
  309. return NULL;
  310. /* next enumerated env var */
  311. memset(env_name, 0, 256);
  312. for (i = 0, str = env; *str != '=' && *str != '\0';)
  313. env_name[i++] = *str++;
  314. env_name[i] = '\0';
  315. return env_name;
  316. }