X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=api%2Fapi.c;h=c7f5db776af9d9e80fe1ac7fcb6718627d48589f;hb=f6f9a016899e62cb65016421a09fd3fe06ce660f;hp=457dc36f6fc4e76a9ff5356414e9c0ba67fe7466;hpb=4d339a9e8a758889de5da16b562aff5601bb3d8d;p=oweals%2Fu-boot.git diff --git a/api/api.c b/api/api.c index 457dc36f6f..c7f5db776a 100644 --- a/api/api.c +++ b/api/api.c @@ -1,18 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2007 Semihalf * * Written by: Rafal Jaworowski - * - * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include +#include #include -#include +#include +#include #include #include +#include #include "api_private.h" @@ -52,7 +54,7 @@ static int API_getc(va_list ap) { 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(); @@ -68,7 +70,7 @@ static int API_tstc(va_list ap) { 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(); @@ -84,7 +86,7 @@ static int API_putc(va_list ap) { 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); @@ -100,7 +102,7 @@ static int API_puts(va_list ap) { 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); @@ -132,7 +134,7 @@ static int API_get_sys_info(va_list ap) { 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; @@ -148,7 +150,7 @@ static int API_udelay(va_list ap) { 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); @@ -164,11 +166,11 @@ static int API_get_timer(va_list ap) { 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; @@ -199,7 +201,7 @@ static int API_dev_enum(va_list ap) 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; @@ -233,7 +235,7 @@ static int API_dev_open(va_list ap) 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; @@ -265,7 +267,7 @@ static int API_dev_close(va_list ap) 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; @@ -295,31 +297,35 @@ static int API_dev_close(va_list ap) /* - * 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; @@ -329,27 +335,40 @@ static int API_dev_write(va_list ap) 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; @@ -387,7 +406,7 @@ static int API_dev_read(va_list ap) 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; @@ -397,23 +416,23 @@ static int API_dev_read(va_list ap) 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; @@ -422,14 +441,14 @@ static int API_dev_read(va_list ap) } 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; @@ -453,12 +472,12 @@ static int API_env_get(va_list ap) { 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; } @@ -476,12 +495,12 @@ static int API_env_set(va_list ap) { 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; } @@ -495,45 +514,47 @@ static int API_env_set(va_list ap) */ 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; } /* @@ -623,7 +644,7 @@ int syscall(int call, int *retval, ...) 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; @@ -661,15 +682,15 @@ void api_init(void) return; } - setenv_hex("api_address", (unsigned long)sig); - 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,