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