1500856ebSRafal Jaworowski /* 2500856ebSRafal Jaworowski * (C) Copyright 2007 Semihalf 3500856ebSRafal Jaworowski * 4500856ebSRafal Jaworowski * Written by: Rafal Jaworowski <raj@semihalf.com> 5500856ebSRafal Jaworowski * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7500856ebSRafal Jaworowski */ 8500856ebSRafal Jaworowski 9500856ebSRafal Jaworowski #include <config.h> 10500856ebSRafal Jaworowski #include <command.h> 11500856ebSRafal Jaworowski #include <common.h> 12500856ebSRafal Jaworowski #include <malloc.h> 13a8409f4fSWolfgang Denk #include <environment.h> 14500856ebSRafal Jaworowski #include <linux/types.h> 15500856ebSRafal Jaworowski #include <api_public.h> 16500856ebSRafal Jaworowski 17500856ebSRafal Jaworowski #include "api_private.h" 18500856ebSRafal Jaworowski 19500856ebSRafal Jaworowski #define DEBUG 20500856ebSRafal Jaworowski #undef DEBUG 21500856ebSRafal Jaworowski 22500856ebSRafal Jaworowski /***************************************************************************** 23500856ebSRafal Jaworowski * 24500856ebSRafal Jaworowski * This is the API core. 25500856ebSRafal Jaworowski * 26500856ebSRafal Jaworowski * API_ functions are part of U-Boot code and constitute the lowest level 27500856ebSRafal Jaworowski * calls: 28500856ebSRafal Jaworowski * 29500856ebSRafal Jaworowski * - they know what values they need as arguments 30500856ebSRafal Jaworowski * - their direct return value pertains to the API_ "shell" itself (0 on 31500856ebSRafal Jaworowski * success, some error code otherwise) 32500856ebSRafal Jaworowski * - if the call returns a value it is buried within arguments 33500856ebSRafal Jaworowski * 34500856ebSRafal Jaworowski ****************************************************************************/ 35500856ebSRafal Jaworowski 36500856ebSRafal Jaworowski #ifdef DEBUG 37500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0) 38500856ebSRafal Jaworowski #else 39500856ebSRafal Jaworowski #define debugf(fmt, args...) 40500856ebSRafal Jaworowski #endif 41500856ebSRafal Jaworowski 42500856ebSRafal Jaworowski typedef int (*cfp_t)(va_list argp); 43500856ebSRafal Jaworowski 44500856ebSRafal Jaworowski static int calls_no; 45500856ebSRafal Jaworowski 46500856ebSRafal Jaworowski /* 47500856ebSRafal Jaworowski * pseudo signature: 48500856ebSRafal Jaworowski * 49500856ebSRafal Jaworowski * int API_getc(int *c) 50500856ebSRafal Jaworowski */ 51500856ebSRafal Jaworowski static int API_getc(va_list ap) 52500856ebSRafal Jaworowski { 53500856ebSRafal Jaworowski int *c; 54500856ebSRafal Jaworowski 5578757d52SStanislav Galabov if ((c = (int *)va_arg(ap, uintptr_t)) == NULL) 56500856ebSRafal Jaworowski return API_EINVAL; 57500856ebSRafal Jaworowski 58500856ebSRafal Jaworowski *c = getc(); 59500856ebSRafal Jaworowski return 0; 60500856ebSRafal Jaworowski } 61500856ebSRafal Jaworowski 62500856ebSRafal Jaworowski /* 63500856ebSRafal Jaworowski * pseudo signature: 64500856ebSRafal Jaworowski * 65500856ebSRafal Jaworowski * int API_tstc(int *c) 66500856ebSRafal Jaworowski */ 67500856ebSRafal Jaworowski static int API_tstc(va_list ap) 68500856ebSRafal Jaworowski { 69500856ebSRafal Jaworowski int *t; 70500856ebSRafal Jaworowski 7178757d52SStanislav Galabov if ((t = (int *)va_arg(ap, uintptr_t)) == NULL) 72500856ebSRafal Jaworowski return API_EINVAL; 73500856ebSRafal Jaworowski 74500856ebSRafal Jaworowski *t = tstc(); 75500856ebSRafal Jaworowski return 0; 76500856ebSRafal Jaworowski } 77500856ebSRafal Jaworowski 78500856ebSRafal Jaworowski /* 79500856ebSRafal Jaworowski * pseudo signature: 80500856ebSRafal Jaworowski * 81500856ebSRafal Jaworowski * int API_putc(char *ch) 82500856ebSRafal Jaworowski */ 83500856ebSRafal Jaworowski static int API_putc(va_list ap) 84500856ebSRafal Jaworowski { 85500856ebSRafal Jaworowski char *c; 86500856ebSRafal Jaworowski 8778757d52SStanislav Galabov if ((c = (char *)va_arg(ap, uintptr_t)) == NULL) 88500856ebSRafal Jaworowski return API_EINVAL; 89500856ebSRafal Jaworowski 90500856ebSRafal Jaworowski putc(*c); 91500856ebSRafal Jaworowski return 0; 92500856ebSRafal Jaworowski } 93500856ebSRafal Jaworowski 94500856ebSRafal Jaworowski /* 95500856ebSRafal Jaworowski * pseudo signature: 96500856ebSRafal Jaworowski * 97500856ebSRafal Jaworowski * int API_puts(char **s) 98500856ebSRafal Jaworowski */ 99500856ebSRafal Jaworowski static int API_puts(va_list ap) 100500856ebSRafal Jaworowski { 101500856ebSRafal Jaworowski char *s; 102500856ebSRafal Jaworowski 10378757d52SStanislav Galabov if ((s = (char *)va_arg(ap, uintptr_t)) == NULL) 104500856ebSRafal Jaworowski return API_EINVAL; 105500856ebSRafal Jaworowski 106500856ebSRafal Jaworowski puts(s); 107500856ebSRafal Jaworowski return 0; 108500856ebSRafal Jaworowski } 109500856ebSRafal Jaworowski 110500856ebSRafal Jaworowski /* 111500856ebSRafal Jaworowski * pseudo signature: 112500856ebSRafal Jaworowski * 113500856ebSRafal Jaworowski * int API_reset(void) 114500856ebSRafal Jaworowski */ 115500856ebSRafal Jaworowski static int API_reset(va_list ap) 116500856ebSRafal Jaworowski { 117500856ebSRafal Jaworowski do_reset(NULL, 0, 0, NULL); 118500856ebSRafal Jaworowski 119500856ebSRafal Jaworowski /* NOT REACHED */ 120500856ebSRafal Jaworowski return 0; 121500856ebSRafal Jaworowski } 122500856ebSRafal Jaworowski 123500856ebSRafal Jaworowski /* 124500856ebSRafal Jaworowski * pseudo signature: 125500856ebSRafal Jaworowski * 126500856ebSRafal Jaworowski * int API_get_sys_info(struct sys_info *si) 127500856ebSRafal Jaworowski * 128500856ebSRafal Jaworowski * fill out the sys_info struct containing selected parameters about the 129500856ebSRafal Jaworowski * machine 130500856ebSRafal Jaworowski */ 131500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap) 132500856ebSRafal Jaworowski { 133500856ebSRafal Jaworowski struct sys_info *si; 134500856ebSRafal Jaworowski 13578757d52SStanislav Galabov si = (struct sys_info *)va_arg(ap, uintptr_t); 136500856ebSRafal Jaworowski if (si == NULL) 137500856ebSRafal Jaworowski return API_ENOMEM; 138500856ebSRafal Jaworowski 139500856ebSRafal Jaworowski return (platform_sys_info(si)) ? 0 : API_ENODEV; 140500856ebSRafal Jaworowski } 141500856ebSRafal Jaworowski 142500856ebSRafal Jaworowski /* 143500856ebSRafal Jaworowski * pseudo signature: 144500856ebSRafal Jaworowski * 145500856ebSRafal Jaworowski * int API_udelay(unsigned long *udelay) 146500856ebSRafal Jaworowski */ 147500856ebSRafal Jaworowski static int API_udelay(va_list ap) 148500856ebSRafal Jaworowski { 149500856ebSRafal Jaworowski unsigned long *d; 150500856ebSRafal Jaworowski 15178757d52SStanislav Galabov if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL) 152500856ebSRafal Jaworowski return API_EINVAL; 153500856ebSRafal Jaworowski 154500856ebSRafal Jaworowski udelay(*d); 155500856ebSRafal Jaworowski return 0; 156500856ebSRafal Jaworowski } 157500856ebSRafal Jaworowski 158500856ebSRafal Jaworowski /* 159500856ebSRafal Jaworowski * pseudo signature: 160500856ebSRafal Jaworowski * 161500856ebSRafal Jaworowski * int API_get_timer(unsigned long *current, unsigned long *base) 162500856ebSRafal Jaworowski */ 163500856ebSRafal Jaworowski static int API_get_timer(va_list ap) 164500856ebSRafal Jaworowski { 165500856ebSRafal Jaworowski unsigned long *base, *cur; 166500856ebSRafal Jaworowski 16778757d52SStanislav Galabov cur = (unsigned long *)va_arg(ap, unsigned long); 168500856ebSRafal Jaworowski if (cur == NULL) 169500856ebSRafal Jaworowski return API_EINVAL; 170500856ebSRafal Jaworowski 17178757d52SStanislav Galabov base = (unsigned long *)va_arg(ap, unsigned long); 172500856ebSRafal Jaworowski if (base == NULL) 173500856ebSRafal Jaworowski return API_EINVAL; 174500856ebSRafal Jaworowski 175500856ebSRafal Jaworowski *cur = get_timer(*base); 176500856ebSRafal Jaworowski return 0; 177500856ebSRafal Jaworowski } 178500856ebSRafal Jaworowski 179500856ebSRafal Jaworowski 180500856ebSRafal Jaworowski /***************************************************************************** 181500856ebSRafal Jaworowski * 182500856ebSRafal Jaworowski * pseudo signature: 183500856ebSRafal Jaworowski * 184500856ebSRafal Jaworowski * int API_dev_enum(struct device_info *) 185500856ebSRafal Jaworowski * 186500856ebSRafal Jaworowski * 187500856ebSRafal Jaworowski * cookies uniqely identify the previously enumerated device instance and 188500856ebSRafal Jaworowski * provide a hint for what to inspect in current enum iteration: 189500856ebSRafal Jaworowski * 190500856ebSRafal Jaworowski * - net: ð_device struct address from list pointed to by eth_devices 191500856ebSRafal Jaworowski * 1924101f687SSimon Glass * - storage: struct blk_desc struct address from &ide_dev_desc[n], 193500856ebSRafal Jaworowski * &scsi_dev_desc[n] and similar tables 194500856ebSRafal Jaworowski * 195500856ebSRafal Jaworowski ****************************************************************************/ 196500856ebSRafal Jaworowski 197500856ebSRafal Jaworowski static int API_dev_enum(va_list ap) 198500856ebSRafal Jaworowski { 199500856ebSRafal Jaworowski struct device_info *di; 200500856ebSRafal Jaworowski 201500856ebSRafal Jaworowski /* arg is ptr to the device_info struct we are going to fill out */ 20278757d52SStanislav Galabov di = (struct device_info *)va_arg(ap, uintptr_t); 203500856ebSRafal Jaworowski if (di == NULL) 204500856ebSRafal Jaworowski return API_EINVAL; 205500856ebSRafal Jaworowski 206500856ebSRafal Jaworowski if (di->cookie == NULL) { 207500856ebSRafal Jaworowski /* start over - clean up enumeration */ 208500856ebSRafal Jaworowski dev_enum_reset(); /* XXX shouldn't the name contain 'stor'? */ 209500856ebSRafal Jaworowski debugf("RESTART ENUM\n"); 210500856ebSRafal Jaworowski 211500856ebSRafal Jaworowski /* net device enumeration first */ 212500856ebSRafal Jaworowski if (dev_enum_net(di)) 213500856ebSRafal Jaworowski return 0; 214500856ebSRafal Jaworowski } 215500856ebSRafal Jaworowski 216500856ebSRafal Jaworowski /* 217500856ebSRafal Jaworowski * The hidden assumption is there can only be one active network 218500856ebSRafal Jaworowski * device and it is identified upon enumeration (re)start, so there's 219500856ebSRafal Jaworowski * no point in trying to find network devices in other cases than the 220500856ebSRafal Jaworowski * (re)start and hence the 'next' device can only be storage 221500856ebSRafal Jaworowski */ 222500856ebSRafal Jaworowski if (!dev_enum_storage(di)) 223500856ebSRafal Jaworowski /* make sure we mark there are no more devices */ 224500856ebSRafal Jaworowski di->cookie = NULL; 225500856ebSRafal Jaworowski 226500856ebSRafal Jaworowski return 0; 227500856ebSRafal Jaworowski } 228500856ebSRafal Jaworowski 229500856ebSRafal Jaworowski 230500856ebSRafal Jaworowski static int API_dev_open(va_list ap) 231500856ebSRafal Jaworowski { 232500856ebSRafal Jaworowski struct device_info *di; 233500856ebSRafal Jaworowski int err = 0; 234500856ebSRafal Jaworowski 235500856ebSRafal Jaworowski /* arg is ptr to the device_info struct */ 23678757d52SStanislav Galabov di = (struct device_info *)va_arg(ap, uintptr_t); 237500856ebSRafal Jaworowski if (di == NULL) 238500856ebSRafal Jaworowski return API_EINVAL; 239500856ebSRafal Jaworowski 240500856ebSRafal Jaworowski /* Allow only one consumer of the device at a time */ 241500856ebSRafal Jaworowski if (di->state == DEV_STA_OPEN) 242500856ebSRafal Jaworowski return API_EBUSY; 243500856ebSRafal Jaworowski 244500856ebSRafal Jaworowski if (di->cookie == NULL) 245500856ebSRafal Jaworowski return API_ENODEV; 246500856ebSRafal Jaworowski 247500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 248500856ebSRafal Jaworowski err = dev_open_stor(di->cookie); 249500856ebSRafal Jaworowski 250500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 251500856ebSRafal Jaworowski err = dev_open_net(di->cookie); 252500856ebSRafal Jaworowski else 253500856ebSRafal Jaworowski err = API_ENODEV; 254500856ebSRafal Jaworowski 255500856ebSRafal Jaworowski if (!err) 256500856ebSRafal Jaworowski di->state = DEV_STA_OPEN; 257500856ebSRafal Jaworowski 258500856ebSRafal Jaworowski return err; 259500856ebSRafal Jaworowski } 260500856ebSRafal Jaworowski 261500856ebSRafal Jaworowski 262500856ebSRafal Jaworowski static int API_dev_close(va_list ap) 263500856ebSRafal Jaworowski { 264500856ebSRafal Jaworowski struct device_info *di; 265500856ebSRafal Jaworowski int err = 0; 266500856ebSRafal Jaworowski 267500856ebSRafal Jaworowski /* arg is ptr to the device_info struct */ 26878757d52SStanislav Galabov di = (struct device_info *)va_arg(ap, uintptr_t); 269500856ebSRafal Jaworowski if (di == NULL) 270500856ebSRafal Jaworowski return API_EINVAL; 271500856ebSRafal Jaworowski 272500856ebSRafal Jaworowski if (di->state == DEV_STA_CLOSED) 273500856ebSRafal Jaworowski return 0; 274500856ebSRafal Jaworowski 275500856ebSRafal Jaworowski if (di->cookie == NULL) 276500856ebSRafal Jaworowski return API_ENODEV; 277500856ebSRafal Jaworowski 278500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 279500856ebSRafal Jaworowski err = dev_close_stor(di->cookie); 280500856ebSRafal Jaworowski 281500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 282500856ebSRafal Jaworowski err = dev_close_net(di->cookie); 283500856ebSRafal Jaworowski else 284500856ebSRafal Jaworowski /* 285500856ebSRafal Jaworowski * In case of unknown device we cannot change its state, so 286500856ebSRafal Jaworowski * only return error code 287500856ebSRafal Jaworowski */ 288500856ebSRafal Jaworowski err = API_ENODEV; 289500856ebSRafal Jaworowski 290500856ebSRafal Jaworowski if (!err) 291500856ebSRafal Jaworowski di->state = DEV_STA_CLOSED; 292500856ebSRafal Jaworowski 293500856ebSRafal Jaworowski return err; 294500856ebSRafal Jaworowski } 295500856ebSRafal Jaworowski 296500856ebSRafal Jaworowski 297500856ebSRafal Jaworowski /* 298500856ebSRafal Jaworowski * Notice: this is for sending network packets only, as U-Boot does not 299500856ebSRafal Jaworowski * support writing to storage at the moment (12.2007) 300500856ebSRafal Jaworowski * 301500856ebSRafal Jaworowski * pseudo signature: 302500856ebSRafal Jaworowski * 303500856ebSRafal Jaworowski * int API_dev_write( 304500856ebSRafal Jaworowski * struct device_info *di, 305500856ebSRafal Jaworowski * void *buf, 306500856ebSRafal Jaworowski * int *len 307500856ebSRafal Jaworowski * ) 308500856ebSRafal Jaworowski * 309500856ebSRafal Jaworowski * buf: ptr to buffer from where to get the data to send 310500856ebSRafal Jaworowski * 311500856ebSRafal Jaworowski * len: length of packet to be sent (in bytes) 312500856ebSRafal Jaworowski * 313500856ebSRafal Jaworowski */ 314500856ebSRafal Jaworowski static int API_dev_write(va_list ap) 315500856ebSRafal Jaworowski { 316500856ebSRafal Jaworowski struct device_info *di; 317500856ebSRafal Jaworowski void *buf; 318500856ebSRafal Jaworowski int *len; 319500856ebSRafal Jaworowski int err = 0; 320500856ebSRafal Jaworowski 321500856ebSRafal Jaworowski /* 1. arg is ptr to the device_info struct */ 32278757d52SStanislav Galabov di = (struct device_info *)va_arg(ap, uintptr_t); 323500856ebSRafal Jaworowski if (di == NULL) 324500856ebSRafal Jaworowski return API_EINVAL; 325500856ebSRafal Jaworowski 326500856ebSRafal Jaworowski /* XXX should we check if device is open? i.e. the ->state ? */ 327500856ebSRafal Jaworowski 328500856ebSRafal Jaworowski if (di->cookie == NULL) 329500856ebSRafal Jaworowski return API_ENODEV; 330500856ebSRafal Jaworowski 331500856ebSRafal Jaworowski /* 2. arg is ptr to buffer from where to get data to write */ 33278757d52SStanislav Galabov buf = (void *)va_arg(ap, uintptr_t); 333500856ebSRafal Jaworowski if (buf == NULL) 334500856ebSRafal Jaworowski return API_EINVAL; 335500856ebSRafal Jaworowski 336500856ebSRafal Jaworowski /* 3. arg is length of buffer */ 33778757d52SStanislav Galabov len = (int *)va_arg(ap, uintptr_t); 338500856ebSRafal Jaworowski if (len == NULL) 339500856ebSRafal Jaworowski return API_EINVAL; 340500856ebSRafal Jaworowski if (*len <= 0) 341500856ebSRafal Jaworowski return API_EINVAL; 342500856ebSRafal Jaworowski 343500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) 344500856ebSRafal Jaworowski /* 345500856ebSRafal Jaworowski * write to storage is currently not supported by U-Boot: 346500856ebSRafal Jaworowski * no storage device implements block_write() method 347500856ebSRafal Jaworowski */ 348500856ebSRafal Jaworowski return API_ENODEV; 349500856ebSRafal Jaworowski 350500856ebSRafal Jaworowski else if (di->type & DEV_TYP_NET) 351500856ebSRafal Jaworowski err = dev_write_net(di->cookie, buf, *len); 352500856ebSRafal Jaworowski else 353500856ebSRafal Jaworowski err = API_ENODEV; 354500856ebSRafal Jaworowski 355500856ebSRafal Jaworowski return err; 356500856ebSRafal Jaworowski } 357500856ebSRafal Jaworowski 358500856ebSRafal Jaworowski 359500856ebSRafal Jaworowski /* 360500856ebSRafal Jaworowski * pseudo signature: 361500856ebSRafal Jaworowski * 362500856ebSRafal Jaworowski * int API_dev_read( 363500856ebSRafal Jaworowski * struct device_info *di, 364500856ebSRafal Jaworowski * void *buf, 365500856ebSRafal Jaworowski * size_t *len, 366500856ebSRafal Jaworowski * unsigned long *start 367500856ebSRafal Jaworowski * size_t *act_len 368500856ebSRafal Jaworowski * ) 369500856ebSRafal Jaworowski * 370500856ebSRafal Jaworowski * buf: ptr to buffer where to put the read data 371500856ebSRafal Jaworowski * 372500856ebSRafal Jaworowski * len: ptr to length to be read 373500856ebSRafal Jaworowski * - network: len of packet to read (in bytes) 374500856ebSRafal Jaworowski * - storage: # of blocks to read (can vary in size depending on define) 375500856ebSRafal Jaworowski * 376500856ebSRafal Jaworowski * start: ptr to start block (only used for storage devices, ignored for 377500856ebSRafal Jaworowski * network) 378500856ebSRafal Jaworowski * 379500856ebSRafal Jaworowski * act_len: ptr to where to put the len actually read 380500856ebSRafal Jaworowski */ 381500856ebSRafal Jaworowski static int API_dev_read(va_list ap) 382500856ebSRafal Jaworowski { 383500856ebSRafal Jaworowski struct device_info *di; 384500856ebSRafal Jaworowski void *buf; 385500856ebSRafal Jaworowski lbasize_t *len_stor, *act_len_stor; 386500856ebSRafal Jaworowski lbastart_t *start; 387500856ebSRafal Jaworowski int *len_net, *act_len_net; 388500856ebSRafal Jaworowski 389500856ebSRafal Jaworowski /* 1. arg is ptr to the device_info struct */ 39078757d52SStanislav Galabov di = (struct device_info *)va_arg(ap, uintptr_t); 391500856ebSRafal Jaworowski if (di == NULL) 392500856ebSRafal Jaworowski return API_EINVAL; 393500856ebSRafal Jaworowski 394500856ebSRafal Jaworowski /* XXX should we check if device is open? i.e. the ->state ? */ 395500856ebSRafal Jaworowski 396500856ebSRafal Jaworowski if (di->cookie == NULL) 397500856ebSRafal Jaworowski return API_ENODEV; 398500856ebSRafal Jaworowski 399500856ebSRafal Jaworowski /* 2. arg is ptr to buffer from where to put the read data */ 40078757d52SStanislav Galabov buf = (void *)va_arg(ap, uintptr_t); 401500856ebSRafal Jaworowski if (buf == NULL) 402500856ebSRafal Jaworowski return API_EINVAL; 403500856ebSRafal Jaworowski 404500856ebSRafal Jaworowski if (di->type & DEV_TYP_STOR) { 405500856ebSRafal Jaworowski /* 3. arg - ptr to var with # of blocks to read */ 40678757d52SStanislav Galabov len_stor = (lbasize_t *)va_arg(ap, uintptr_t); 407500856ebSRafal Jaworowski if (!len_stor) 408500856ebSRafal Jaworowski return API_EINVAL; 409500856ebSRafal Jaworowski if (*len_stor <= 0) 410500856ebSRafal Jaworowski return API_EINVAL; 411500856ebSRafal Jaworowski 412500856ebSRafal Jaworowski /* 4. arg - ptr to var with start block */ 41378757d52SStanislav Galabov start = (lbastart_t *)va_arg(ap, uintptr_t); 414500856ebSRafal Jaworowski 415500856ebSRafal Jaworowski /* 5. arg - ptr to var where to put the len actually read */ 41678757d52SStanislav Galabov act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t); 417500856ebSRafal Jaworowski if (!act_len_stor) 418500856ebSRafal Jaworowski return API_EINVAL; 419500856ebSRafal Jaworowski 420500856ebSRafal Jaworowski *act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start); 421500856ebSRafal Jaworowski 422500856ebSRafal Jaworowski } else if (di->type & DEV_TYP_NET) { 423500856ebSRafal Jaworowski 424500856ebSRafal Jaworowski /* 3. arg points to the var with length of packet to read */ 42578757d52SStanislav Galabov len_net = (int *)va_arg(ap, uintptr_t); 426500856ebSRafal Jaworowski if (!len_net) 427500856ebSRafal Jaworowski return API_EINVAL; 428500856ebSRafal Jaworowski if (*len_net <= 0) 429500856ebSRafal Jaworowski return API_EINVAL; 430500856ebSRafal Jaworowski 431500856ebSRafal Jaworowski /* 4. - ptr to var where to put the len actually read */ 43278757d52SStanislav Galabov act_len_net = (int *)va_arg(ap, uintptr_t); 433500856ebSRafal Jaworowski if (!act_len_net) 434500856ebSRafal Jaworowski return API_EINVAL; 435500856ebSRafal Jaworowski 436500856ebSRafal Jaworowski *act_len_net = dev_read_net(di->cookie, buf, *len_net); 437500856ebSRafal Jaworowski 438500856ebSRafal Jaworowski } else 439500856ebSRafal Jaworowski return API_ENODEV; 440500856ebSRafal Jaworowski 441500856ebSRafal Jaworowski return 0; 442500856ebSRafal Jaworowski } 443500856ebSRafal Jaworowski 444500856ebSRafal Jaworowski 445500856ebSRafal Jaworowski /* 446500856ebSRafal Jaworowski * pseudo signature: 447500856ebSRafal Jaworowski * 448500856ebSRafal Jaworowski * int API_env_get(const char *name, char **value) 449500856ebSRafal Jaworowski * 450500856ebSRafal Jaworowski * name: ptr to name of env var 451500856ebSRafal Jaworowski */ 452500856ebSRafal Jaworowski static int API_env_get(va_list ap) 453500856ebSRafal Jaworowski { 454500856ebSRafal Jaworowski char *name, **value; 455500856ebSRafal Jaworowski 45678757d52SStanislav Galabov if ((name = (char *)va_arg(ap, uintptr_t)) == NULL) 457500856ebSRafal Jaworowski return API_EINVAL; 45878757d52SStanislav Galabov if ((value = (char **)va_arg(ap, uintptr_t)) == NULL) 459500856ebSRafal Jaworowski return API_EINVAL; 460500856ebSRafal Jaworowski 461500856ebSRafal Jaworowski *value = getenv(name); 462500856ebSRafal Jaworowski 463500856ebSRafal Jaworowski return 0; 464500856ebSRafal Jaworowski } 465500856ebSRafal Jaworowski 466500856ebSRafal Jaworowski /* 467500856ebSRafal Jaworowski * pseudo signature: 468500856ebSRafal Jaworowski * 469500856ebSRafal Jaworowski * int API_env_set(const char *name, const char *value) 470500856ebSRafal Jaworowski * 471500856ebSRafal Jaworowski * name: ptr to name of env var 472500856ebSRafal Jaworowski * 473500856ebSRafal Jaworowski * value: ptr to value to be set 474500856ebSRafal Jaworowski */ 475500856ebSRafal Jaworowski static int API_env_set(va_list ap) 476500856ebSRafal Jaworowski { 477500856ebSRafal Jaworowski char *name, *value; 478500856ebSRafal Jaworowski 47978757d52SStanislav Galabov if ((name = (char *)va_arg(ap, uintptr_t)) == NULL) 480500856ebSRafal Jaworowski return API_EINVAL; 48178757d52SStanislav Galabov if ((value = (char *)va_arg(ap, uintptr_t)) == NULL) 482500856ebSRafal Jaworowski return API_EINVAL; 483500856ebSRafal Jaworowski 484*382bee57SSimon Glass env_set(name, value); 485500856ebSRafal Jaworowski 486500856ebSRafal Jaworowski return 0; 487500856ebSRafal Jaworowski } 488500856ebSRafal Jaworowski 489500856ebSRafal Jaworowski /* 490500856ebSRafal Jaworowski * pseudo signature: 491500856ebSRafal Jaworowski * 492500856ebSRafal Jaworowski * int API_env_enum(const char *last, char **next) 493500856ebSRafal Jaworowski * 494500856ebSRafal Jaworowski * last: ptr to name of env var found in last iteration 495500856ebSRafal Jaworowski */ 496500856ebSRafal Jaworowski static int API_env_enum(va_list ap) 497500856ebSRafal Jaworowski { 4986215bd4cSEmmanuel Vadot int i, buflen; 4996215bd4cSEmmanuel Vadot char *last, **next, *s; 5006215bd4cSEmmanuel Vadot ENTRY *match, search; 5016215bd4cSEmmanuel Vadot static char *var; 502500856ebSRafal Jaworowski 50378757d52SStanislav Galabov last = (char *)va_arg(ap, unsigned long); 504500856ebSRafal Jaworowski 50578757d52SStanislav Galabov if ((next = (char **)va_arg(ap, uintptr_t)) == NULL) 506500856ebSRafal Jaworowski return API_EINVAL; 507500856ebSRafal Jaworowski 5086215bd4cSEmmanuel Vadot if (last == NULL) { 5096215bd4cSEmmanuel Vadot var = NULL; 5106215bd4cSEmmanuel Vadot i = 0; 5116215bd4cSEmmanuel Vadot } else { 5126215bd4cSEmmanuel Vadot var = strdup(last); 5136215bd4cSEmmanuel Vadot s = strchr(var, '='); 5146215bd4cSEmmanuel Vadot if (s != NULL) 5156215bd4cSEmmanuel Vadot *s = 0; 5166215bd4cSEmmanuel Vadot search.key = var; 5176215bd4cSEmmanuel Vadot i = hsearch_r(search, FIND, &match, &env_htab, 0); 5186215bd4cSEmmanuel Vadot if (i == 0) { 5196215bd4cSEmmanuel Vadot i = API_EINVAL; 5206215bd4cSEmmanuel Vadot goto done; 5216215bd4cSEmmanuel Vadot } 5226215bd4cSEmmanuel Vadot } 523500856ebSRafal Jaworowski 5246215bd4cSEmmanuel Vadot /* match the next entry after i */ 5256215bd4cSEmmanuel Vadot i = hmatch_r("", i, &match, &env_htab); 5266215bd4cSEmmanuel Vadot if (i == 0) 5276215bd4cSEmmanuel Vadot goto done; 5286215bd4cSEmmanuel Vadot buflen = strlen(match->key) + strlen(match->data) + 2; 5296215bd4cSEmmanuel Vadot var = realloc(var, buflen); 5306215bd4cSEmmanuel Vadot snprintf(var, buflen, "%s=%s", match->key, match->data); 5316215bd4cSEmmanuel Vadot *next = var; 532500856ebSRafal Jaworowski return 0; 533500856ebSRafal Jaworowski 5346215bd4cSEmmanuel Vadot done: 5356215bd4cSEmmanuel Vadot free(var); 5366215bd4cSEmmanuel Vadot var = NULL; 537500856ebSRafal Jaworowski *next = NULL; 5386215bd4cSEmmanuel Vadot return i; 539500856ebSRafal Jaworowski } 540500856ebSRafal Jaworowski 541a2a5729fSChe-Liang Chiou /* 542a2a5729fSChe-Liang Chiou * pseudo signature: 543a2a5729fSChe-Liang Chiou * 544a2a5729fSChe-Liang Chiou * int API_display_get_info(int type, struct display_info *di) 545a2a5729fSChe-Liang Chiou */ 546a2a5729fSChe-Liang Chiou static int API_display_get_info(va_list ap) 547a2a5729fSChe-Liang Chiou { 548a2a5729fSChe-Liang Chiou int type; 549a2a5729fSChe-Liang Chiou struct display_info *di; 550a2a5729fSChe-Liang Chiou 551a2a5729fSChe-Liang Chiou type = va_arg(ap, int); 552a2a5729fSChe-Liang Chiou di = va_arg(ap, struct display_info *); 553a2a5729fSChe-Liang Chiou 554a2a5729fSChe-Liang Chiou return display_get_info(type, di); 555a2a5729fSChe-Liang Chiou } 556a2a5729fSChe-Liang Chiou 557a2a5729fSChe-Liang Chiou /* 558a2a5729fSChe-Liang Chiou * pseudo signature: 559a2a5729fSChe-Liang Chiou * 560a2a5729fSChe-Liang Chiou * int API_display_draw_bitmap(ulong bitmap, int x, int y) 561a2a5729fSChe-Liang Chiou */ 562a2a5729fSChe-Liang Chiou static int API_display_draw_bitmap(va_list ap) 563a2a5729fSChe-Liang Chiou { 564a2a5729fSChe-Liang Chiou ulong bitmap; 565a2a5729fSChe-Liang Chiou int x, y; 566a2a5729fSChe-Liang Chiou 567a2a5729fSChe-Liang Chiou bitmap = va_arg(ap, ulong); 568a2a5729fSChe-Liang Chiou x = va_arg(ap, int); 569a2a5729fSChe-Liang Chiou y = va_arg(ap, int); 570a2a5729fSChe-Liang Chiou 571a2a5729fSChe-Liang Chiou return display_draw_bitmap(bitmap, x, y); 572a2a5729fSChe-Liang Chiou } 573a2a5729fSChe-Liang Chiou 574a2a5729fSChe-Liang Chiou /* 575a2a5729fSChe-Liang Chiou * pseudo signature: 576a2a5729fSChe-Liang Chiou * 577a2a5729fSChe-Liang Chiou * void API_display_clear(void) 578a2a5729fSChe-Liang Chiou */ 579a2a5729fSChe-Liang Chiou static int API_display_clear(va_list ap) 580a2a5729fSChe-Liang Chiou { 581a2a5729fSChe-Liang Chiou display_clear(); 582a2a5729fSChe-Liang Chiou return 0; 583a2a5729fSChe-Liang Chiou } 584a2a5729fSChe-Liang Chiou 585500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, }; 586500856ebSRafal Jaworowski 587500856ebSRafal Jaworowski /* 588500856ebSRafal Jaworowski * The main syscall entry point - this is not reentrant, only one call is 589500856ebSRafal Jaworowski * serviced until finished. 590500856ebSRafal Jaworowski * 591500856ebSRafal Jaworowski * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); 592500856ebSRafal Jaworowski * 593500856ebSRafal Jaworowski * call: syscall number 594500856ebSRafal Jaworowski * 595500856ebSRafal Jaworowski * retval: points to the return value placeholder, this is the place the 596500856ebSRafal Jaworowski * syscall puts its return value, if NULL the caller does not 597500856ebSRafal Jaworowski * expect a return value 598500856ebSRafal Jaworowski * 599500856ebSRafal Jaworowski * ... syscall arguments (variable number) 600500856ebSRafal Jaworowski * 601500856ebSRafal Jaworowski * returns: 0 if the call not found, 1 if serviced 602500856ebSRafal Jaworowski */ 603500856ebSRafal Jaworowski int syscall(int call, int *retval, ...) 604500856ebSRafal Jaworowski { 605500856ebSRafal Jaworowski va_list ap; 606500856ebSRafal Jaworowski int rv; 607500856ebSRafal Jaworowski 60820e5ed13SJean-Christophe PLAGNIOL-VILLARD if (call < 0 || call >= calls_no) { 609500856ebSRafal Jaworowski debugf("invalid call #%d\n", call); 610500856ebSRafal Jaworowski return 0; 611500856ebSRafal Jaworowski } 612500856ebSRafal Jaworowski 613500856ebSRafal Jaworowski if (calls_table[call] == NULL) { 614500856ebSRafal Jaworowski debugf("syscall #%d does not have a handler\n", call); 615500856ebSRafal Jaworowski return 0; 616500856ebSRafal Jaworowski } 617500856ebSRafal Jaworowski 618500856ebSRafal Jaworowski va_start(ap, retval); 619500856ebSRafal Jaworowski rv = calls_table[call](ap); 620500856ebSRafal Jaworowski if (retval != NULL) 621500856ebSRafal Jaworowski *retval = rv; 622500856ebSRafal Jaworowski 623500856ebSRafal Jaworowski return 1; 624500856ebSRafal Jaworowski } 625500856ebSRafal Jaworowski 626500856ebSRafal Jaworowski void api_init(void) 627500856ebSRafal Jaworowski { 6285cc9e6b7Sxypron.glpk@gmx.de struct api_signature *sig; 629500856ebSRafal Jaworowski 630500856ebSRafal Jaworowski /* TODO put this into linker set one day... */ 631500856ebSRafal Jaworowski calls_table[API_RSVD] = NULL; 632500856ebSRafal Jaworowski calls_table[API_GETC] = &API_getc; 633500856ebSRafal Jaworowski calls_table[API_PUTC] = &API_putc; 634500856ebSRafal Jaworowski calls_table[API_TSTC] = &API_tstc; 635500856ebSRafal Jaworowski calls_table[API_PUTS] = &API_puts; 636500856ebSRafal Jaworowski calls_table[API_RESET] = &API_reset; 637500856ebSRafal Jaworowski calls_table[API_GET_SYS_INFO] = &API_get_sys_info; 638500856ebSRafal Jaworowski calls_table[API_UDELAY] = &API_udelay; 639500856ebSRafal Jaworowski calls_table[API_GET_TIMER] = &API_get_timer; 640500856ebSRafal Jaworowski calls_table[API_DEV_ENUM] = &API_dev_enum; 641500856ebSRafal Jaworowski calls_table[API_DEV_OPEN] = &API_dev_open; 642500856ebSRafal Jaworowski calls_table[API_DEV_CLOSE] = &API_dev_close; 643500856ebSRafal Jaworowski calls_table[API_DEV_READ] = &API_dev_read; 644500856ebSRafal Jaworowski calls_table[API_DEV_WRITE] = &API_dev_write; 645500856ebSRafal Jaworowski calls_table[API_ENV_GET] = &API_env_get; 646500856ebSRafal Jaworowski calls_table[API_ENV_SET] = &API_env_set; 647500856ebSRafal Jaworowski calls_table[API_ENV_ENUM] = &API_env_enum; 648a2a5729fSChe-Liang Chiou calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info; 649a2a5729fSChe-Liang Chiou calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap; 650a2a5729fSChe-Liang Chiou calls_table[API_DISPLAY_CLEAR] = &API_display_clear; 651500856ebSRafal Jaworowski calls_no = API_MAXCALL; 652500856ebSRafal Jaworowski 653500856ebSRafal Jaworowski debugf("API initialized with %d calls\n", calls_no); 654500856ebSRafal Jaworowski 655500856ebSRafal Jaworowski dev_stor_init(); 656500856ebSRafal Jaworowski 657500856ebSRafal Jaworowski /* 658500856ebSRafal Jaworowski * Produce the signature so the API consumers can find it 659500856ebSRafal Jaworowski */ 660500856ebSRafal Jaworowski sig = malloc(sizeof(struct api_signature)); 661500856ebSRafal Jaworowski if (sig == NULL) { 662500856ebSRafal Jaworowski printf("API: could not allocate memory for the signature!\n"); 663500856ebSRafal Jaworowski return; 664500856ebSRafal Jaworowski } 665500856ebSRafal Jaworowski 66622aa61f7SStanislav Galabov setenv_hex("api_address", (unsigned long)sig); 66778757d52SStanislav Galabov debugf("API sig @ 0x%lX\n", (unsigned long)sig); 668500856ebSRafal Jaworowski memcpy(sig->magic, API_SIG_MAGIC, 8); 669500856ebSRafal Jaworowski sig->version = API_SIG_VERSION; 670500856ebSRafal Jaworowski sig->syscall = &syscall; 671500856ebSRafal Jaworowski sig->checksum = 0; 672500856ebSRafal Jaworowski sig->checksum = crc32(0, (unsigned char *)sig, 673500856ebSRafal Jaworowski sizeof(struct api_signature)); 67478757d52SStanislav Galabov debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall); 675500856ebSRafal Jaworowski } 676500856ebSRafal Jaworowski 677500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size, 678500856ebSRafal Jaworowski int flags) 679500856ebSRafal Jaworowski { 680500856ebSRafal Jaworowski int i; 681500856ebSRafal Jaworowski 682500856ebSRafal Jaworowski if (!si->mr || !size || (flags == 0)) 683500856ebSRafal Jaworowski return; 684500856ebSRafal Jaworowski 685500856ebSRafal Jaworowski /* find free slot */ 686500856ebSRafal Jaworowski for (i = 0; i < si->mr_no; i++) 687500856ebSRafal Jaworowski if (si->mr[i].flags == 0) { 688500856ebSRafal Jaworowski /* insert new mem region */ 689500856ebSRafal Jaworowski si->mr[i].start = start; 690500856ebSRafal Jaworowski si->mr[i].size = size; 691500856ebSRafal Jaworowski si->mr[i].flags = flags; 692500856ebSRafal Jaworowski return; 693500856ebSRafal Jaworowski } 694500856ebSRafal Jaworowski } 695