+// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2007 Semihalf
*
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- *
*/
#include <config.h>
#include <command.h>
#include <common.h>
+#include <env.h>
#include <malloc.h>
-#include <environment.h>
+#include <env_internal.h>
+#include <linux/delay.h>
#include <linux/types.h>
#include <api_public.h>
+#include <u-boot/crc.h>
#include "api_private.h"
{
int *c;
- if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
+ if ((c = (int *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
*c = getc();
{
int *t;
- if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
+ if ((t = (int *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
*t = tstc();
{
char *c;
- if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
+ if ((c = (char *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
putc(*c);
{
char *s;
- if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
+ if ((s = (char *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
puts(s);
{
struct sys_info *si;
- si = (struct sys_info *)va_arg(ap, u_int32_t);
+ si = (struct sys_info *)va_arg(ap, uintptr_t);
if (si == NULL)
return API_ENOMEM;
{
unsigned long *d;
- if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
+ if ((d = (unsigned long *)va_arg(ap, unsigned long)) == NULL)
return API_EINVAL;
udelay(*d);
{
unsigned long *base, *cur;
- cur = (unsigned long *)va_arg(ap, u_int32_t);
+ cur = (unsigned long *)va_arg(ap, unsigned long);
if (cur == NULL)
return API_EINVAL;
- base = (unsigned long *)va_arg(ap, u_int32_t);
+ base = (unsigned long *)va_arg(ap, unsigned long);
if (base == NULL)
return API_EINVAL;
*
* - net: ð_device struct address from list pointed to by eth_devices
*
- * - storage: block_dev_desc_t struct address from &ide_dev_desc[n],
+ * - storage: struct blk_desc struct address from &ide_dev_desc[n],
* &scsi_dev_desc[n] and similar tables
*
****************************************************************************/
struct device_info *di;
/* arg is ptr to the device_info struct we are going to fill out */
- di = (struct device_info *)va_arg(ap, u_int32_t);
+ di = (struct device_info *)va_arg(ap, uintptr_t);
if (di == NULL)
return API_EINVAL;
int err = 0;
/* arg is ptr to the device_info struct */
- di = (struct device_info *)va_arg(ap, u_int32_t);
+ di = (struct device_info *)va_arg(ap, uintptr_t);
if (di == NULL)
return API_EINVAL;
int err = 0;
/* arg is ptr to the device_info struct */
- di = (struct device_info *)va_arg(ap, u_int32_t);
+ di = (struct device_info *)va_arg(ap, uintptr_t);
if (di == NULL)
return API_EINVAL;
/*
- * Notice: this is for sending network packets only, as U-Boot does not
- * support writing to storage at the moment (12.2007)
- *
* pseudo signature:
*
* int API_dev_write(
* struct device_info *di,
* void *buf,
- * int *len
+ * int *len,
+ * unsigned long *start
* )
*
* buf: ptr to buffer from where to get the data to send
*
- * len: length of packet to be sent (in bytes)
+ * len: ptr to length to be read
+ * - network: len of packet to be sent (in bytes)
+ * - storage: # of blocks to write (can vary in size depending on define)
*
+ * start: ptr to start block (only used for storage devices, ignored for
+ * network)
*/
static int API_dev_write(va_list ap)
{
struct device_info *di;
void *buf;
- int *len;
+ lbasize_t *len_stor, act_len_stor;
+ lbastart_t *start;
+ int *len_net;
int err = 0;
/* 1. arg is ptr to the device_info struct */
- di = (struct device_info *)va_arg(ap, u_int32_t);
+ di = (struct device_info *)va_arg(ap, uintptr_t);
if (di == NULL)
return API_EINVAL;
return API_ENODEV;
/* 2. arg is ptr to buffer from where to get data to write */
- buf = (void *)va_arg(ap, u_int32_t);
+ buf = (void *)va_arg(ap, uintptr_t);
if (buf == NULL)
return API_EINVAL;
- /* 3. arg is length of buffer */
- len = (int *)va_arg(ap, u_int32_t);
- if (len == NULL)
- return API_EINVAL;
- if (*len <= 0)
- return API_EINVAL;
+ if (di->type & DEV_TYP_STOR) {
+ /* 3. arg - ptr to var with # of blocks to write */
+ len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
+ if (!len_stor)
+ return API_EINVAL;
+ if (*len_stor <= 0)
+ return API_EINVAL;
- if (di->type & DEV_TYP_STOR)
- /*
- * write to storage is currently not supported by U-Boot:
- * no storage device implements block_write() method
- */
- return API_ENODEV;
+ /* 4. arg - ptr to var with start block */
+ start = (lbastart_t *)va_arg(ap, uintptr_t);
+
+ act_len_stor = dev_write_stor(di->cookie, buf, *len_stor, *start);
+ if (act_len_stor != *len_stor) {
+ debugf("write @ %llu: done %llu out of %llu blocks",
+ (uint64_t)blk, (uint64_t)act_len_stor,
+ (uint64_t)len_stor);
+ return API_EIO;
+ }
- else if (di->type & DEV_TYP_NET)
- err = dev_write_net(di->cookie, buf, *len);
- else
+ } else if (di->type & DEV_TYP_NET) {
+ /* 3. arg points to the var with length of packet to write */
+ len_net = (int *)va_arg(ap, uintptr_t);
+ if (!len_net)
+ return API_EINVAL;
+ if (*len_net <= 0)
+ return API_EINVAL;
+
+ err = dev_write_net(di->cookie, buf, *len_net);
+
+ } else
err = API_ENODEV;
return err;
int *len_net, *act_len_net;
/* 1. arg is ptr to the device_info struct */
- di = (struct device_info *)va_arg(ap, u_int32_t);
+ di = (struct device_info *)va_arg(ap, uintptr_t);
if (di == NULL)
return API_EINVAL;
return API_ENODEV;
/* 2. arg is ptr to buffer from where to put the read data */
- buf = (void *)va_arg(ap, u_int32_t);
+ buf = (void *)va_arg(ap, uintptr_t);
if (buf == NULL)
return API_EINVAL;
if (di->type & DEV_TYP_STOR) {
/* 3. arg - ptr to var with # of blocks to read */
- len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
+ len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
if (!len_stor)
return API_EINVAL;
if (*len_stor <= 0)
return API_EINVAL;
/* 4. arg - ptr to var with start block */
- start = (lbastart_t *)va_arg(ap, u_int32_t);
+ start = (lbastart_t *)va_arg(ap, uintptr_t);
/* 5. arg - ptr to var where to put the len actually read */
- act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
+ act_len_stor = (lbasize_t *)va_arg(ap, uintptr_t);
if (!act_len_stor)
return API_EINVAL;
} else if (di->type & DEV_TYP_NET) {
/* 3. arg points to the var with length of packet to read */
- len_net = (int *)va_arg(ap, u_int32_t);
+ len_net = (int *)va_arg(ap, uintptr_t);
if (!len_net)
return API_EINVAL;
if (*len_net <= 0)
return API_EINVAL;
/* 4. - ptr to var where to put the len actually read */
- act_len_net = (int *)va_arg(ap, u_int32_t);
+ act_len_net = (int *)va_arg(ap, uintptr_t);
if (!act_len_net)
return API_EINVAL;
{
char *name, **value;
- if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
+ if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
- if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
+ if ((value = (char **)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
- *value = getenv(name);
+ *value = env_get(name);
return 0;
}
{
char *name, *value;
- if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
+ if ((name = (char *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
- if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
+ if ((value = (char *)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
- setenv(name, value);
+ env_set(name, value);
return 0;
}
*/
static int API_env_enum(va_list ap)
{
- int i, n;
- char *last, **next;
+ int i, buflen;
+ char *last, **next, *s;
+ struct env_entry *match, search;
+ static char *var;
- last = (char *)va_arg(ap, u_int32_t);
+ last = (char *)va_arg(ap, unsigned long);
- if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
+ if ((next = (char **)va_arg(ap, uintptr_t)) == NULL)
return API_EINVAL;
- if (last == NULL)
- /* start over */
- *next = ((char *)env_get_addr(0));
- else {
- *next = last;
-
- for (i = 0; env_get_char(i) != '\0'; i = n + 1) {
- for (n = i; env_get_char(n) != '\0'; ++n) {
- if (n >= CONFIG_ENV_SIZE) {
- /* XXX shouldn't we set *next = NULL?? */
- return 0;
- }
- }
-
- if (envmatch((uchar *)last, i) < 0)
- continue;
-
- /* try to get next name */
- i = n + 1;
- if (env_get_char(i) == '\0') {
- /* no more left */
- *next = NULL;
- return 0;
- }
-
- *next = ((char *)env_get_addr(i));
- return 0;
+ if (last == NULL) {
+ var = NULL;
+ i = 0;
+ } else {
+ var = strdup(last);
+ s = strchr(var, '=');
+ if (s != NULL)
+ *s = 0;
+ search.key = var;
+ i = hsearch_r(search, ENV_FIND, &match, &env_htab, 0);
+ if (i == 0) {
+ i = API_EINVAL;
+ goto done;
}
}
+ /* match the next entry after i */
+ i = hmatch_r("", i, &match, &env_htab);
+ if (i == 0)
+ goto done;
+ buflen = strlen(match->key) + strlen(match->data) + 2;
+ var = realloc(var, buflen);
+ snprintf(var, buflen, "%s=%s", match->key, match->data);
+ *next = var;
return 0;
+
+done:
+ free(var);
+ var = NULL;
+ *next = NULL;
+ return i;
}
/*
void api_init(void)
{
- struct api_signature *sig = NULL;
+ struct api_signature *sig;
/* TODO put this into linker set one day... */
calls_table[API_RSVD] = NULL;
return;
}
- debugf("API sig @ 0x%08x\n", sig);
+ env_set_hex("api_address", (unsigned long)sig);
+ debugf("API sig @ 0x%lX\n", (unsigned long)sig);
memcpy(sig->magic, API_SIG_MAGIC, 8);
sig->version = API_SIG_VERSION;
sig->syscall = &syscall;
sig->checksum = 0;
sig->checksum = crc32(0, (unsigned char *)sig,
sizeof(struct api_signature));
- debugf("syscall entry: 0x%08x\n", sig->syscall);
+ debugf("syscall entry: 0x%lX\n", (unsigned long)sig->syscall);
}
void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,