diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c index 1a726a8aaaba151b8a7b4ba682a2425fddd6ce86..31dafb2eb483640730f6cee4bcfa67c6d46813b0 100644 --- a/common/fdt_wrappers.c +++ b/common/fdt_wrappers.c @@ -10,6 +10,7 @@ #include <debug.h> #include <fdt_wrappers.h> #include <libfdt.h> +#include <string.h> /* * Read cells from a given property of the given node. At most 2 cells of the @@ -39,7 +40,6 @@ int fdtw_read_cells(const void *dtb, int node, const char *prop, return -1; } - /* Verify that property length accords with cell length */ if (NCELLS((unsigned int)value_len) != cells) { WARN("Property length mismatch\n"); @@ -61,6 +61,77 @@ int fdtw_read_cells(const void *dtb, int node, const char *prop, return 0; } +/* + * Read cells from a given property of the given node. Any number of 32-bit + * cells of the property can be read. The fdt pointer is updated. Returns 0 on + * success, and -1 on error. + */ +int fdtw_read_array(const void *dtb, int node, const char *prop, + unsigned int cells, void *value) +{ + const uint32_t *value_ptr; + int value_len; + + assert(dtb != NULL); + assert(prop != NULL); + assert(value != NULL); + assert(node >= 0); + + /* Access property and obtain its length (in bytes) */ + value_ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), + &value_len); + if (value_ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length accords with cell length */ + if (NCELLS((unsigned int)value_len) != cells) { + WARN("Property length mismatch\n"); + return -1; + } + + uint32_t *dst = value; + + for (unsigned int i = 0U; i < cells; i++) { + dst[i] = fdt32_to_cpu(value_ptr[i]); + } + + return 0; +} + +/* + * Read string from a given property of the given node. Up to 'size - 1' + * characters are read, and a NUL terminator is added. Returns 0 on success, + * and -1 upon error. + */ +int fdtw_read_string(const void *dtb, int node, const char *prop, + char *str, size_t size) +{ + const char *ptr; + size_t len; + + assert(dtb != NULL); + assert(node >= 0); + assert(prop != NULL); + assert(str != NULL); + assert(size > 0U); + + ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + len = strlcpy(str, ptr, size); + if (len >= size) { + WARN("String of property %s in dtb has been truncated\n", prop); + return -1; + } + + return 0; +} + /* * Write cells in place to a given property of the given node. At most 2 cells * of the property are written. Returns 0 on success, and -1 upon error. diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h index 3eae944e5bb8fca29047651eafb4b9eb94c04a54..c8d753f9ab7f7b5c96f9c906202eafa6ecdc61f7 100644 --- a/include/common/fdt_wrappers.h +++ b/include/common/fdt_wrappers.h @@ -14,6 +14,11 @@ int fdtw_read_cells(const void *dtb, int node, const char *prop, unsigned int cells, void *value); +int fdtw_read_array(const void *dtb, int node, const char *prop, + unsigned int cells, void *value); +int fdtw_read_string(const void *dtb, int node, const char *prop, + char *str, size_t size); int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, unsigned int cells, void *value); + #endif /* __FDT_WRAPPERS__ */ diff --git a/include/lib/libc/string.h b/include/lib/libc/string.h index 3c8e3b65e2d0aed4812650dd006e7d2d11e50bec..ee6eeacef94eceed811a76bb0cc7bf5c15807b81 100644 --- a/include/lib/libc/string.h +++ b/include/lib/libc/string.h @@ -28,5 +28,6 @@ void *memset(void *dst, int val, size_t count); size_t strlen(const char *s); size_t strnlen(const char *s, size_t maxlen); char *strrchr(const char *p, int ch); +size_t strlcpy(char * dst, const char * src, size_t dsize); #endif /* STRING_H */ diff --git a/lib/libc/libc.mk b/lib/libc/libc.mk index daa2ec102cb86b20d1560faabbf4be2f27133ab3..1276f5c82b8bae2e9925f02beff0c81b484b22d5 100644 --- a/lib/libc/libc.mk +++ b/lib/libc/libc.mk @@ -19,6 +19,7 @@ LIBC_SRCS := $(addprefix lib/libc/, \ snprintf.c \ strchr.c \ strcmp.c \ + strlcpy.c \ strlen.c \ strncmp.c \ strnlen.c \ diff --git a/lib/libc/strlcpy.c b/lib/libc/strlcpy.c new file mode 100644 index 0000000000000000000000000000000000000000..c4f39bb9ba50b4d60531e93432edd59354373372 --- /dev/null +++ b/lib/libc/strlcpy.c @@ -0,0 +1,52 @@ +/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */ + +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdint.h> +#include <string.h> + +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ +size_t +strlcpy(char * dst, const char * src, size_t dsize) +{ + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ +}