X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=api%2Fapi.c;h=c7f5db776af9d9e80fe1ac7fcb6718627d48589f;hb=f6f9a016899e62cb65016421a09fd3fe06ce660f;hp=8a1433af78a98357f8e7ac58773c2b32a49aebad;hpb=78757d52c8b27f7f33ab4035706796a414c81128;p=oweals%2Fu-boot.git diff --git a/api/api.c b/api/api.c index 8a1433af78..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" @@ -295,27 +297,31 @@ 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 */ @@ -333,23 +339,36 @@ static int API_dev_write(va_list ap) if (buf == NULL) return API_EINVAL; - /* 3. arg is length of buffer */ - len = (int *)va_arg(ap, uintptr_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); - else if (di->type & DEV_TYP_NET) - err = dev_write_net(di->cookie, buf, *len); - else + 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) { + /* 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; @@ -458,7 +477,7 @@ static int API_env_get(va_list ap) if ((value = (char **)va_arg(ap, uintptr_t)) == NULL) return API_EINVAL; - *value = getenv(name); + *value = env_get(name); return 0; } @@ -481,7 +500,7 @@ static int API_env_set(va_list ap) 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, unsigned long); 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,7 +682,7 @@ void api_init(void) return; } - setenv_hex("api_address", (unsigned long)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;